⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mngprfx.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    DWORD dwType;
    DWORD dwVal;
    DWORD dwValSize;
    DWORD i;

    // At least name of upstream interface needs to be provided
    if (UpIfName == NULL) goto cleanup;

    // Convert names of interfaces
    _sntprintf(szDownIfName, MAX_REG_STR, TEXT("%hs"), DownIfName != NULL ? DownIfName : "\0");
    szDownIfName[MAX_REG_STR - 1] = TEXT('\0');

    // Open the key containing settings of the up-stream interface
    _sntprintf(szRegValue, MAX_REG_STR, TEXT("%s\\%hs"), DHCPV6_REGKEY_BASE, UpIfName);
    szRegValue[MAX_REG_STR - 1] = TEXT('\0');
    if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, szRegValue, 0,
                                      0, &hKey)) {
        hKey = INVALID_HANDLE_VALUE;
        goto cleanup;
    }

    // Check whether the upstream interface should participate in PD
    dwValSize = sizeof(dwVal);
    dwType = REG_DWORD;
    if (ERROR_SUCCESS != RegQueryValueEx(hKey, DHCPV6_REGVAL_ACCEPT_PD, NULL,
                                         &dwType, (LPBYTE)&dwVal, &dwValSize)
        || dwType != REG_DWORD)
        goto cleanup;
    
    if (dwVal == 0) {
        // This interface is not supposed to participate in PD
        goto cleanup;
    }
    if (dwVal == 1 && szDownIfName[0] == TEXT('\0')) {
        // This interface is supposed to participate in PD; no need to check
        // downstream interface because it is not provided
        fRet = TRUE;
        goto cleanup;
    }

    // Check list of downstream interfaces
    dwValSize = MAX_REG_STR * sizeof(TCHAR);
    dwType = REG_MULTI_SZ;
    if (ERROR_SUCCESS != RegQueryValueEx(hKey, DHCPV6_REGVAL_DOWNSTREAM_IFS, NULL,
                                         &dwType, (LPBYTE)szRegValue, &dwValSize)
        || dwType != REG_MULTI_SZ)
        goto cleanup;
    
    // Try to find the downstream interface in the list
    for (i = 0; i < MAX_REG_STR;) {
        if (! _tcscmp(&szRegValue[i], szDownIfName))
            // Found it!
            break;

        i += _tcslen(&szRegValue[i]) + 1;
        if (szRegValue[i] == TEXT('\0'))
            // End of list; didn't find the interface
            goto cleanup;
    }
    fRet = TRUE;

cleanup:
    if (hKey != INVALID_HANDLE_VALUE) RegCloseKey(hKey);
    return fRet;
}

//
// Install new (or refresh) prefix on the system. This function will assign (refresh)
// given prefix on all applicable interfaces.
//
BOOL DHCPv6ManagePrefix(
    UINT OrigIfIdx,         // Interface on which prefix was received
    IPv6Addr Prefix,        // The prefix
    UINT PrefixLen,         //   Length
    UINT ValidLifetime,     //   Valid lifetime; Note: can use INFINITE_LIFETIME
    UINT PreferredLifetime  //   Preferred lifetime; Note: can use INFINITE_LIFETIME
) {
    BOOL fRet = FALSE; // Be pessimistic
    PIP_ADAPTER_ADDRESSES pAADownStreamIfArray[MAX_DOWNSTREAM_IFS];
    PIP_ADAPTER_ADDRESSES pAdapterAddresses = NULL;
    PIP_ADAPTER_ADDRESSES pAAIncomingIf = NULL;
    PIP_ADAPTER_ADDRESSES pAA;
    USHORT DownStreamIfCount;
    ULONG ulFlags;
    ULONG ulBufferLength;
    USHORT usAttempts;
    UINT i;

    ASSERT(g_hIPv6Stack != INVALID_HANDLE_VALUE);

    // The passed-in prefix may actually be longer than required
    TrimPrefix(&Prefix, PrefixLen);

    // Get a list of all interfaces in the system
    ulFlags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST
              | GAA_FLAG_INCLUDE_PREFIX;
    pAdapterAddresses = NULL;
    ulBufferLength = 0;
    usAttempts = 0;
    for (;;) {
        DWORD dwError;
        
        dwError = GetAdaptersAddresses(AF_UNSPEC, ulFlags, NULL,
                                       pAdapterAddresses, &ulBufferLength);
        if (dwError == ERROR_SUCCESS)
            break;
        else if (dwError == ERROR_BUFFER_OVERFLOW
                 && ++usAttempts < 4) {
            if (pAdapterAddresses != NULL)
                free(pAdapterAddresses);
            pAdapterAddresses = (PIP_ADAPTER_ADDRESSES)malloc(ulBufferLength);
        } else
            goto cleanup;
    }
    
    // Find the interface on which we received the Prefix delegation
    for (pAA = pAdapterAddresses, pAAIncomingIf = NULL;
         pAA != NULL; pAA = pAA->Next) {

        if (pAA->Ipv6IfIndex == OrigIfIdx) {
            pAAIncomingIf = pAA;
            break;
        }
    }
    if (pAAIncomingIf == NULL)
        // We couldn't find the incoming interface; just give up
        goto cleanup;

    // Consult with registry to determine whether the interface on which
    // we recieved PD is a valid upstream interface
    if (! IsPDEnabledInterface(pAAIncomingIf->AdapterName, NULL))
        goto cleanup;

    // Find interfaces that are eligible for prefix assignment
    DownStreamIfCount = 0;
    for (pAA = pAdapterAddresses;
         pAA != NULL && DownStreamIfCount < MAX_DOWNSTREAM_IFS;
         pAA = pAA->Next) {

        // Accept only Ethernet interfaces
        if (pAA->IfType != IF_TYPE_ETHERNET_CSMACD) continue;
        
        // Cannot be the same interface on which we recieved the prefix
        if (pAA->Ipv6IfIndex == OrigIfIdx) continue;

        // Consult with registry to determine whether this is one of the
        // valid downstream interfaces
        if (! IsPDEnabledInterface(pAAIncomingIf->AdapterName, pAA->AdapterName))
            continue;
        
        // This interface is eligible for prefix assignment, remember it
        pAADownStreamIfArray[DownStreamIfCount++] = pAA;

        DEBUGMSG(1,
            (TEXT("DHCPv6ManagePrefix: IF# [%d] is eligible for prefix assignment\r\n"),
            pAA->Ipv6IfIndex));
    }

    // Given number of eligible interfaces for prefix assignment, if:
    // a) no interfaces, then ignore the prefix
    // b) one or more interface, then subnet prefix between interfaces
    //    on interface index number.
    //
    // Note: We could handle (b) to not to subnet prefix if we have
    //       only one downstream interface, but handling dynamic interface
    //       creation would be more complicated.
    // 
    if (DownStreamIfCount == 0) goto cleanup;
    
    for (i = 0; i < DownStreamIfCount; i+=1) {
        PIP_ADAPTER_PREFIX pAP;
        IPv6Addr NewPrefix;
        UINT NewPrefixLen;
        
        pAA = pAADownStreamIfArray[i];

        // Check whether the interface already has the prefix
        for (pAP = pAA->FirstPrefix; pAP != NULL; pAP = pAP->Next) {
            IPv6Addr ThisPrefix;

            if (pAP->PrefixLength == 0 || pAP->PrefixLength == 128) continue;

            ThisPrefix = *GetIpFromSockAddr(&pAP->Address);
            
            TrimPrefix(&ThisPrefix, PrefixLen);
            if (IN6_ADDR_EQUAL(&ThisPrefix, &Prefix)) {

                NewPrefix = *GetIpFromSockAddr(&pAP->Address);
                NewPrefixLen = pAP->PrefixLength;

                break;
            }
        }

        if (pAP == NULL) {
            // The Prefix has never been assigned to this interface; generate one.
            if (! CreateSubnetPrefix(&Prefix, PrefixLen, (USHORT)pAA->Ipv6IfIndex,
                                     &NewPrefix, &NewPrefixLen))
                goto cleanup;
        }

        DEBUGMSG(1,
            (TEXT("DHCPv6ManagePrefix: %s prefix for IF# [%d]\r\n"),
            pAP == NULL ? TEXT("Creating") : TEXT("Refreshing"),
            pAA->Ipv6IfIndex));

        if (! SetOrRefreshPrefix(pAAIncomingIf,
                                 pAA,
                                 &NewPrefix, 
                                 NewPrefixLen,
                                 ValidLifetime,     
                                 PreferredLifetime)) {
            goto cleanup;
        }
    }
    fRet = TRUE;

cleanup:
    if (pAdapterAddresses != NULL)
        free(pAdapterAddresses);
   
    return fRet;
}

//
// Intended to be called periodically to clean-up expired routes.
//
BOOL DHCPv6ManagePrefixPeriodicCleanup() {
    // Cleanup routes
    IPV6_QUERY_ROUTE_TABLE Query, NextQuery;
    IPV6_INFO_ROUTE_TABLE Route;
    UINT BytesReturned;

    ASSERT(g_hIPv6Stack != INVALID_HANDLE_VALUE);

    NextQuery.Neighbor.IF.Index = 0;
    for (;;) {
        Query = NextQuery;

        if (! DeviceIoControl(g_hIPv6Stack,
                              IOCTL_IPV6_QUERY_ROUTE_TABLE,
                              &Query, sizeof Query,
                              &Route, sizeof Route,
                              &BytesReturned, NULL)) {
            return FALSE;
        }

        NextQuery = Route.Next;

        if (Query.Neighbor.IF.Index != 0) {
            Route.This = Query;

            if (Route.Type == RTE_TYPE_AUTOCONF &&
                Route.ValidLifetime == 0 &&
                Route.Publish) {

                // This route has been configured by DHCPv6 earlier, but is
                // no longer valid. We'll stop publishing it so that it can
                // be cleaned-up by the stack.
                //
                UpdateRoute(Route.This.Neighbor.IF.Index,
                            &Route.This.Neighbor.Address,
                            &Route.This.Prefix, Route.This.PrefixLength,
                            Route.ValidLifetime, Route.PreferredLifetime,
                            Route.Preference, FALSE);
            }
        }
        
        if (NextQuery.Neighbor.IF.Index == 0)
            break;
    }
    return TRUE;
}

BOOL DHCPv6ManagePrefixInit() {
    ASSERT(g_hIPv6Stack == INVALID_HANDLE_VALUE);

    if (g_hIPv6Stack == INVALID_HANDLE_VALUE) {
        // Get handle to IPv6 stack for DeviceIoControl calls
        g_hIPv6Stack = CreateFileW(L"IP60:",
                                   GENERIC_WRITE,
                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
                                   NULL,   // security attributes
                                   OPEN_EXISTING,
                                   0,      // flags & attributes
                                   NULL);  // template file
        if (g_hIPv6Stack == INVALID_HANDLE_VALUE) {
            ASSERT(FALSE);
            return FALSE;
        }
    }

    return TRUE;
}

void DHCPv6ManagePrefixDeinit() {
    if (g_hIPv6Stack != INVALID_HANDLE_VALUE) CloseHandle(g_hIPv6Stack);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -