Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  DHCPUtils.cpp   Sprache: C

 
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#include "DHCPUtils.h"
#include <vector>
#include "mozilla/Logging.h"
#include "nsString.h"

#define MOZ_WORKING_BUFFER_SIZE_NETWORK_ADAPTERS 15000
#define MOZ_WORKING_BUFFER_SIZE_DHCP_PARAMS 1000
#define MOZ_MAX_TRIES 3
namespace mozilla {
namespace toolkit {
namespace system {
namespace windowsDHCPClient {

//
// The comments on this page reference the following Microsoft documentation
// pages (both retrieved 2017-06-27)
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa365915(v=vs.85).aspx
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa363298(v=vs.85).aspx
mozilla::LazyLogModule gDhcpUtilsLog("dhcpUtils");

#undef LOG
#define LOG(args) MOZ_LOG(gDhcpUtilsLog, LogLevel::Debug, args)

bool IsCurrentAndHasDHCP(PIP_ADAPTER_ADDRESSES aAddresses) {
  return aAddresses->OperStatus == 1 &&
         (aAddresses->Dhcpv4Server.iSockaddrLength ||
          aAddresses->Dhcpv6Server.iSockaddrLength);
}

nsresult GetActiveDHCPNetworkAdapterName(
    nsACString& aNetworkAdapterName,
    WindowsNetworkFunctionsWrapper* aWindowsNetworkFunctionsWrapper) {
  /* Declare and initialize variables */

  uint32_t dwRetVal = 0;
  nsresult rv = NS_ERROR_FAILURE;

  // Set the flags to pass to GetAdaptersAddresses
  uint32_t flags = GAA_FLAG_INCLUDE_PREFIX;

  // default to unspecified address family (both)
  uint32_t family = AF_UNSPEC;

  // Allocate a 15 KB buffer to start with.
  uint32_t outBufLen = MOZ_WORKING_BUFFER_SIZE_NETWORK_ADAPTERS;
  uint32_t iterations = 0;

  aNetworkAdapterName.Truncate();

  // Now we try calling the GetAdaptersAddresses method until the return value
  // is not ERROR_BUFFER_OVERFLOW. According to [1]
  //
  //
  // > When the return value is ERROR_BUFFER_OVERFLOW, the SizePointer parameter
  // returned > points to the required size of the buffer to hold the adapter
  // information. > Note that it is possible for the buffer size required for
  // the IP_ADAPTER_ADDRESSES > structures pointed to by the AdapterAddresses
  // parameter to change between > subsequent calls to the GetAdaptersAddresses
  // function if an adapter address > is added or removed. However, this method
  // of using the GetAdaptersAddresses > function is strongly discouraged. This
  // method requires calling the > GetAdaptersAddresses function multiple times.
  // >
  // > The recommended method of calling the GetAdaptersAddresses function is
  // > to pre-allocate a 15KB working buffer pointed to by the AdapterAddresses
  // parameter. > On typical computers, this dramatically reduces the chances
  // that the > GetAdaptersAddresses function returns ERROR_BUFFER_OVERFLOW,
  // which would require > calling GetAdaptersAddresses function multiple times.
  //
  //
  // The possibility of the buffer size changing between calls to
  // GetAdaptersAddresses is why we allow the following code to be called
  // several times, rather than just the two that would be neccessary if we
  // could rely on the value returned in outBufLen being the true size needed.

  std::vector<IP_ADAPTER_ADDRESSES> pAddresses;
  do {
    // resize outBufLen up to the next multiple of sizeof(IP_ADAPTER_ADDRESSES)
    outBufLen = ((outBufLen + sizeof(IP_ADAPTER_ADDRESSES) - 1) /
                 sizeof(IP_ADAPTER_ADDRESSES)) *
                sizeof(IP_ADAPTER_ADDRESSES);
    pAddresses.resize(outBufLen / sizeof(IP_ADAPTER_ADDRESSES));
    LOG(
        ("Trying GetAdaptersAddresses with pAddresses sized to %zu and buffer "
         "length of %d",
         pAddresses.size(), outBufLen));

    dwRetVal = aWindowsNetworkFunctionsWrapper->GetAdaptersAddressesWrapped(
        family, flags, nullptr, pAddresses.data(), (PULONG)&outBufLen);

    if (dwRetVal == ERROR_BUFFER_OVERFLOW) {
      iterations++;
    }
  } while (dwRetVal == ERROR_BUFFER_OVERFLOW && iterations < MOZ_MAX_TRIES);

  switch (dwRetVal) {
    case NO_ERROR: {
      // set default return value if we don't find a suitable network adapter
      rv = NS_ERROR_NOT_AVAILABLE;
      PIP_ADAPTER_ADDRESSES pCurrAddresses = pAddresses.data();
      while (pCurrAddresses) {
        if (IsCurrentAndHasDHCP(pCurrAddresses)) {
          rv = NS_OK;
          aNetworkAdapterName.Assign(pCurrAddresses->AdapterName);
          break;
        }
        pCurrAddresses = pCurrAddresses->Next;
      }
    } break;
    case ERROR_NO_DATA:
      rv = NS_ERROR_NOT_AVAILABLE;
      break;
    default:
      MOZ_LOG(gDhcpUtilsLog, mozilla::LogLevel::Warning,
              ("GetAdaptersAddresses returned %d", dwRetVal));
      rv = NS_ERROR_FAILURE;
      break;
  }
  return rv;
}

DWORD
IterateDHCPInformRequestsUntilBufferLargeEnough(
    DHCPCAPI_PARAMS& aDhcpRequestedOptionParams,
    wchar_t* aWideNetworkAdapterName, std::vector<char>& aBuffer,
    WindowsNetworkFunctionsWrapper* aWindowsNetworkFunctionsWrapper) {
  uint32_t iterations = 0;
  uint32_t outBufLen = MOZ_WORKING_BUFFER_SIZE_DHCP_PARAMS;

  DHCPCAPI_PARAMS_ARRAY RequestParams = {1,  // only one option to request
                                         &aDhcpRequestedOptionParams};

  // According to [2],
  // the following is for 'Optional data to be requested,
  // in addition to the data requested in the RecdParams array.'
  // We are not requesting anything in addition, so this is empty.
  DHCPCAPI_PARAMS_ARRAY SendParams = {0, nullptr};

  DWORD winAPIResponse;
  // Now we try calling the DHCPRequestParams method until the return value
  // is not ERROR_MORE_DATA. According to [2]:
  //
  //
  // > Note that the required size of Buffer may increase during the time that
  // elapses > between the initial function call's return and a subsequent call;
  // > therefore, the required size of Buffer (indicated in pSize)
  // > provides an indication of the approximate size required of Buffer,
  // > rather than guaranteeing that subsequent calls will return successfully
  // > if Buffer is set to the size indicated in pSize.
  //
  //
  // This is why we allow this DHCPRequestParams to be called several times,
  // rather than just the two that would be neccessary if we could rely on the
  // value returned in outBufLen being the true size needed.
  do {
    aBuffer.resize(outBufLen);

    winAPIResponse = aWindowsNetworkFunctionsWrapper->DhcpRequestParamsWrapped(
        DHCPCAPI_REQUEST_SYNCHRONOUS,  // Flags
        nullptr,                       // Reserved
        aWideNetworkAdapterName,       // Adapter Name
        nullptr,                       // not using class id
        SendParams,                    // sent parameters
        RequestParams,                 // requesting params
        (PBYTE)aBuffer.data(),         // buffer for the output of RequestParams
        (PULONG)&outBufLen,            // buffer size
        nullptr  // Request ID for persistent requests - not needed here
    );

    if (winAPIResponse == ERROR_MORE_DATA) {
      iterations++;
    }
  } while (winAPIResponse == ERROR_MORE_DATA && iterations < MOZ_MAX_TRIES);
  return winAPIResponse;
}

nsresult RetrieveOption(
    const nsACString& aAdapterName, uint8_t aOption,
    std::vector<char>& aOptionValueBuf, uint32_t* aOptionSize,
    WindowsNetworkFunctionsWrapper* aWindowsNetworkFunctionsWrapper) {
  nsresult rv;
  nsAutoString wideNetworkAdapterName = NS_ConvertUTF8toUTF16(aAdapterName);

  DHCPCAPI_PARAMS DhcpRequestedOptionParams = {
      0,        //  Flags - Reserved, must be set to zero [2]
      aOption,  // OptionId
      false,    // whether this is vendor specific - let's assume not
      nullptr,  // data filled in on return
      0         // nBytes used by return data
  };

  std::vector<char> tmpBuffer(
      MOZ_WORKING_BUFFER_SIZE_DHCP_PARAMS);  // a buffer for the DHCP response
                                             // object
  DWORD winAPIResponse = IterateDHCPInformRequestsUntilBufferLargeEnough(
      DhcpRequestedOptionParams, wideNetworkAdapterName.get(), tmpBuffer,
      aWindowsNetworkFunctionsWrapper);

  switch (winAPIResponse) {
    case NO_ERROR: {
      if (DhcpRequestedOptionParams.nBytesData == 0) {
        *aOptionSize = 0;
        rv = NS_ERROR_NOT_AVAILABLE;
        break;
      }

      if (*aOptionSize >= DhcpRequestedOptionParams.nBytesData) {
        rv = NS_OK;
      } else {
        rv = NS_ERROR_LOSS_OF_SIGNIFICANT_DATA;
      }

      uint32_t actualSizeReturned =
          *aOptionSize > DhcpRequestedOptionParams.nBytesData
              ? DhcpRequestedOptionParams.nBytesData
              : *aOptionSize;

      memcpy(aOptionValueBuf.data(), DhcpRequestedOptionParams.Data,
             actualSizeReturned);
      *aOptionSize = DhcpRequestedOptionParams.nBytesData;
      break;
    }
    case ERROR_INVALID_PARAMETER:
      MOZ_LOG(gDhcpUtilsLog, mozilla::LogLevel::Warning,
              ("RetrieveOption returned %lu (ERROR_INVALID_PARAMETER) when "
               "option %d requested",
               winAPIResponse, aOption));
      rv = NS_ERROR_INVALID_ARG;
      break;
    default:
      MOZ_LOG(gDhcpUtilsLog, mozilla::LogLevel::Warning,
              ("RetrieveOption returned %lu when option %d requested",
               winAPIResponse, aOption));
      rv = NS_ERROR_FAILURE;
  }
  return rv;
}

}  // namespace windowsDHCPClient
}  // namespace system
}  // namespace toolkit
}  // namespace mozilla

Messung V0.5
C=86 H=96 G=90

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge