Announcement

Collapse
No announcement yet.

Querying a DHCP server for DNS server identities

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Querying a DHCP server for DNS server identities

    i posted this in response to a discussion in the source code section
    (http://"]http://l]
    as a matter of fact, the machine does not have any of these keys:
    hkey_local_machine\system\currentcontrolset\services\tcpip or any of its subkeys
    hkey_local_machine\system\currentcontrolset\services\vxd\mstcp\dhcpnameserver
    hkey_local_machine\system\currentcontrolset\services\vxd\mstcp\nameserver

    also no dns info shows up in any of the subkeys of the dhcp area, hkey_local_machine\system\currentcontrolset\services\vxd\dhcp

    i presume there must be a way to actively query the dhcp
    server directly for identities of the dynamically allocated dnss that
    appear in winipcfg. anyone know how?

    ------------------
    michael burns

    [this message has been edited by michael burns (edited may 15, 2001).]
    Michael Burns

  • #2
    FIXED_INFO
    The FIXED_INFO structure contains information that is the same across all the interfaces in a computer.

    typedef struct {
    char HostName[MAX_HOSTNAME_LEN + 4] ;
    char DomainName[MAX_DOMAIN_NAME_LEN + 4];
    PIP_ADDR_STRING CurrentDnsServer;
    IP_ADDR_STRING DnsServerList;
    UINT NodeType;
    char ScopeId[MAX_SCOPE_ID_LEN + 4];
    UINT EnableRouting;
    UINT EnableProxy;
    UINT EnableDns;
    } FIXED_INFO, *PFIXED_INFO;
    Members
    HostName[MAX_HOSTNAME_LEN + 4]
    Specifies the host name for the local computer.
    DomainName[MAX_DOMAIN_NAME_LEN + 4]
    Specifies the domain in which the local computer is registered.
    CurrentDnsServer
    Specifies the current DNS server.
    DnsServerList
    Specifies the set of DNS servers used by the local computer.
    NodeType
    Specifies whether the local computer uses dynamic host configuration protocol (DHCP).
    ScopeId[MAX_SCOPE_ID_LEN + 4]
    Specifies the DHCP scope name.
    EnableRouting
    Specifies whether routing is enabled on the local computer.
    EnableProxy
    Specifies whether the local computer is acting as an ARP proxy.
    EnableDns
    Specifies whether DNS is enabled on the local computer.
    Requirements
    Windows NT/2000: Requires Windows 2000.
    Windows 95/98: Requires Windows 98.
    Header: Declared in Iptypes.h.

    See Also
    GetNetworkParams




    [This message has been edited by John McWilliams (edited May 15, 2001).]

    Comment


    • #3
      Thanks! That lead me in the right direction. I have kludged up a
      quick and dirty demo that seems to work.

      Code:
      '
      '   Quick & Dirty test. by Michael Burns 15-May-01
      '
      '
      #COMPILE EXE
      #DIM ALL
      #INCLUDE "WIN32API.INC"
      '
      TYPE IP_ADDRESS_STRING
          IpAddressString(4 * 4 - 1) AS BYTE
      END TYPE
      '
      TYPE IP_MASK_STRING
          IpMaskString(4 * 4 - 1) AS BYTE
      END TYPE
      '
      TYPE IP_ADDR_STRING
          lNext      AS LONG
          IpAddress AS IP_ADDRESS_STRING
          IpMask    AS IP_MASK_STRING
          Context   AS LONG
      END TYPE
      '
      %MAX_HOSTNAME_LEN = 128
      %MAX_DOMAIN_NAME_LEN = 128
      %MAX_SCOPE_ID_LEN = 256
      '
      TYPE FIXED_INFO
          HostName(%MAX_HOSTNAME_LEN + 4 - 1)AS BYTE
          DomainName(%MAX_DOMAIN_NAME_LEN + 4 - 1) AS BYTE
          CurrentDnsServer AS LONG
          DnsServerList    AS IP_ADDR_STRING
          NodeType         AS LONG
          ScopeId(%MAX_SCOPE_ID_LEN + 4 - 1) AS BYTE
          EnableRouting    AS LONG
          EnableProxy      AS LONG
          EnableDns        AS LONG
      END TYPE
      ' Declare is done in a manner where we can use loadlibrary in case
      ' PC does not have iphlpapi.dll in it (like old Win 95 systems)
      '
      DECLARE FUNCTION GetNetworkParams ALIAS "GetNetworkParams" (BYREF pFixedInfo AS ANY, BYREF pOutBufLen AS LONG) AS LONG
      '
      ' Declare of the movememory in a more flexable manner that winapi32.inc
      ' and comment out the MoveMemory in winapi32.inc
      '
      DECLARE FUNCTION MoveMemory LIB "KERNEL32.DLL" ALIAS "RtlMoveMemory" (lpDest AS ANY, lpSource AS ANY, BYVAL cbMove AS LONG) AS LONG
      %ERROR_NOT_SUPPORTED = 50
      %ERROR_BUFFER_OVERFLOW = 111
      %ERROR_INVALID_PARAMETER = 87
      %ERROR_NO_DATA = 232
      '
      FUNCTION IpToString(BYVAL ip AS LONG) AS STRING
        ' Don't remember where I got this function
        ' (I might have written it, but I might not.)
        LOCAL b AS BYTE PTR
      '
        b = VARPTR(ip)
        FUNCTION = FORMAT$(@b[0]) & "." & FORMAT$(@b[1]) & "." & _
                   FORMAT$(@b[2]) & "." & FORMAT$(@b[3])
      '
      END FUNCTION
      '*********************************************
      FUNCTION PBMAIN() AS LONG
          LOCAL lngFixedInfoNeeded    AS LONG
          LOCAL bytFixedInfoBuffer()  AS BYTE
          LOCAL udtFixedInfo          AS FIXED_INFO
          LOCAL strFixedInfoScopeId   AS STRING
          LOCAL lngWin32apiResultCode AS LONG
          LOCAL ProcessID AS LONG
          LOCAL hLib AS LONG
          LOCAL ProcAddr AS DWORD
          ' Here we see if iphlpapi.dll is on this machine
          ProcessID = GetCurrentProcessId()
          hLib = LoadLibrary("iphlpapi.dll")
          IF ISFALSE hLib THEN
             MSGBOX "Sorry, iphlpapi.dll not supported on this machine. Terminating program."
             EXIT FUNCTION
          END IF
          'Retrieve FUNCTION address
          ProcAddr = GetProcAddress(hLib,"GetNetworkParams")
          IF ProcAddr = %NULL THEN
             MSGBOX "Sorry, GetNetworkParams not supported on this machine. Terminating program."
             EXIT FUNCTION
          END IF
          lngFixedInfoNeeded=LEN(udtFixedInfo)
          'Call pointer to the function using function prototype
          CALL DWORD ProcAddr USING GetNetworkParams(BYVAL %NULL , lngFixedInfoNeeded) TO lngWin32apiResultCode
          IF lngWin32apiResultCode <> 0 THEN
             SELECT CASE lngWin32apiResultCode
                  CASE %ERROR_BUFFER_OVERFLOW
                      ' Right-size bytFixedInfoBuffer
                      REDIM bytFixedInfoBuffer (lngFixedInfoNeeded)
                  CASE %ERROR_INVALID_PARAMETER
                      MSGBOX "Invalid parameter Error."
                      EXIT FUNCTION
                  CASE %ERROR_NO_DATA
                      MSGBOX "No data Error."
                      EXIT FUNCTION
                  CASE %ERROR_NOT_SUPPORTED
                      MSGBOX "Not Supported Error."
                      EXIT FUNCTION
                  CASE ELSE
                      MSGBOX STR$(lngWin32apiResultCode) + " error code returned."
                      EXIT FUNCTION
             END SELECT
          ELSE
             ' Something is horribly wrong as we should not get 0
             ' for the first pass through. Get outta here!
             MSGBOX "Unexpected result. Terminating program."
             EXIT FUNCTION
          END IF
          'Call pointer to the function using function prototype
          CALL DWORD ProcAddr USING GetNetworkParams(bytFixedInfoBuffer(0) , lngFixedInfoNeeded) TO lngWin32apiResultCode
          MoveMemory  udtFixedInfo, bytFixedInfoBuffer(0),  LEN(udtFixedInfo)
          MSGBOX "Current DNS Server: "+udtFixedInfo.DnsServerList.IpAddress
      END FUNCTION


      [This message has been edited by Michael Burns (edited May 15, 2001).]
      Michael Burns

      Comment


      • #4
        If you don't want to modify the MoveMemory declaration, then substitute the following line:
        Code:
        POKE$ VARPTR(udtFixedInfo), PEEK$(VARPTR(bytFixedInfoBuffer(0)), LEN(udtFixedInfo))
        Or you can use the original MoveMemory declaration with the following line:
        Code:
        MoveMemory VARPTR(udtFixedInfo), VARPTR(bytFixedInfoBuffer(0)), LEN(udtFixedInfo)
        ------------------
        Lance
        PowerBASIC Support
        mailto:[email protected][email protected]</A>
        Lance
        mailto:[email protected]

        Comment


        • #5
          Thanks Lance! Here it is with your change to clean up the MoveMemory,
          as well as a change at the end to enumerate any other DNS servers,
          and I had forgotten above to drop the IPtoString as it is not used.
          The other thing to note is this seems to work both with PC's whose
          DNS assignments come from a DHCP server as well as on machines with
          fixed DNS assignments made through the control panel. I suppose the
          next logical step is for me to figure out how to generalize it to
          multiple adapters.

          Code:
          '
          '   Quick & Dirty test #2. by Michael Burns 16-May-01
          '
          '
          #COMPILE EXE
          #DIM ALL
          #INCLUDE "WIN32API.INC"
          '
          TYPE IP_ADDRESS_STRING
              IpAddressString(4 * 4 - 1) AS BYTE
          END TYPE
          '
          TYPE IP_MASK_STRING
              IpMaskString(4 * 4 - 1) AS BYTE
          END TYPE
          '
          TYPE IP_ADDR_STRING
              lNext      AS LONG
              IpAddress AS IP_ADDRESS_STRING
              IpMask    AS IP_MASK_STRING
              Context   AS LONG
          END TYPE
          '
          %MAX_HOSTNAME_LEN = 128
          %MAX_DOMAIN_NAME_LEN = 128
          %MAX_SCOPE_ID_LEN = 256
          '
          TYPE FIXED_INFO
              HostName(%MAX_HOSTNAME_LEN + 4 - 1)AS BYTE
              DomainName(%MAX_DOMAIN_NAME_LEN + 4 - 1) AS BYTE
              CurrentDnsServer AS LONG
              DnsServerList    AS IP_ADDR_STRING
              NodeType         AS LONG
              ScopeId(%MAX_SCOPE_ID_LEN + 4 - 1) AS BYTE
              EnableRouting    AS LONG
              EnableProxy      AS LONG
              EnableDns        AS LONG
          END TYPE
          ' Declare is done in a manner where we can use loadlibrary in case
          ' PC does not have iphlpapi.dll on it (like old Win 95 systems don't).
          '
          DECLARE FUNCTION GetNetworkParams ALIAS "GetNetworkParams" (BYREF pFixedInfo AS ANY, BYREF pOutBufLen AS LONG) AS LONG
          '
          '
          %ERROR_NOT_SUPPORTED = 50
          %ERROR_BUFFER_OVERFLOW = 111
          %ERROR_INVALID_PARAMETER = 87
          %ERROR_NO_DATA = 232
          '
          '*********************************************
          FUNCTION PBMAIN() AS LONG
              LOCAL lngFixedInfoNeeded    AS LONG
              LOCAL bytFixedInfoBuffer()  AS BYTE
              LOCAL udtFixedInfo          AS FIXED_INFO
              LOCAL Buffer AS IP_ADDR_STRING
              LOCAL strFixedInfoScopeId   AS STRING
              LOCAL lngWin32apiResultCode AS LONG
              LOCAL ProcessID AS LONG
              LOCAL hLib AS LONG
              LOCAL ProcAddr AS DWORD
              LOCAL pAddrStr AS LONG
              LOCAL I AS INTEGER
              ' Here we see if iphlpapi.dll is on this machine
              ProcessID = GetCurrentProcessId()
              hLib = LoadLibrary("iphlpapi.dll")
              IF ISFALSE hLib THEN
                 MSGBOX "Sorry, iphlpapi.dll not supported on this machine. Terminating program."
                 EXIT FUNCTION
              END IF
              'Retrieve FUNCTION address
              ProcAddr = GetProcAddress(hLib,"GetNetworkParams")
              IF ProcAddr = %NULL THEN
                 MSGBOX "Sorry, GetNetworkParams not supported on this machine. Terminating program."
                 EXIT FUNCTION
              END IF
              lngFixedInfoNeeded=LEN(udtFixedInfo)
              'Call pointer to the function using function prototype
              CALL DWORD ProcAddr USING GetNetworkParams(BYVAL %NULL , lngFixedInfoNeeded) TO lngWin32apiResultCode
              IF lngWin32apiResultCode <> 0 THEN
                 SELECT CASE lngWin32apiResultCode
                      CASE %ERROR_BUFFER_OVERFLOW
                          ' Right-size bytFixedInfoBuffer
                          REDIM bytFixedInfoBuffer (lngFixedInfoNeeded)
                      CASE %ERROR_INVALID_PARAMETER
                          MSGBOX "Invalid parameter Error."
                          EXIT FUNCTION
                      CASE %ERROR_NO_DATA
                          MSGBOX "No data Error."
                          EXIT FUNCTION
                      CASE %ERROR_NOT_SUPPORTED
                          MSGBOX "Not Supported Error."
                          EXIT FUNCTION
                      CASE ELSE
                          MSGBOX STR$(lngWin32apiResultCode) + " error code returned."
                          EXIT FUNCTION
                 END SELECT
              ELSE
                 ' Something is horribly wrong as we should not get 0
                 ' for the first pass through. Get outta here!
                 MSGBOX "Unexpected result. Terminating program."
                 EXIT FUNCTION
              END IF
              'Call pointer to the function using function prototype
              CALL DWORD ProcAddr USING GetNetworkParams(bytFixedInfoBuffer(0) , lngFixedInfoNeeded) TO lngWin32apiResultCode
              MoveMemory VARPTR(udtFixedInfo), VARPTR(bytFixedInfoBuffer(0)), LEN(udtFixedInfo)
              MSGBOX "DNS Server #1:  " & udtFixedInfo.DnsServerList.IpAddress
              pAddrStr = udtFixedInfo.DnsServerList.lNext
              I=1
              DO WHILE pAddrStr <> 0
                  I=I+1
                  MoveMemory VARPTR(Buffer), pAddrStr, LEN(Buffer)
                  MSGBOX "DNS Server#"+TRIM$(STR$(I))+":  " & Buffer.IpAddress
                  pAddrStr = Buffer.lNext
              LOOP
          '    
          END FUNCTION

          ------------------
          Michael Burns

          [This message has been edited by Michael Burns (edited May 16, 2001).]
          Michael Burns

          Comment


          • #6
            Hi Michael

            nice one - I'll add the GetNetworkParams() option to DNSQRY
            - this'll round it up. Note that this method does not work
            on PCs with no network adapter (like PCs connecting via a
            modem to an ISP and getting a dynamic address) so that in
            such cases it's still necessary to fall back on alternative
            methods (such as looking in the registry, etc) to get the
            DNS server(s).

            Just as an aside there seemed to be a problem (the post is
            date 1999 so the situation may have changed) with GetNetworkParams
            in special situations. Follow this link for the discussion on
            this issue:
            http://www.stardust.com/hypermail/winsock2/0596.html

            UPDATE: looking around it seems to be only supported on Win2000
            and Win98 - I'll add it anyway

            Cheers

            Florent


            ------------------




            [This message has been edited by Florent Heyworth (edited May 16, 2001).]

            Comment


            • #7
              hi michael

              i added getnetworkparams to the code at http://www.powerbasic.com/support/pb...ad.php?t=24950
              could you test it and tell me if my implementation works
              (it returns not supported on my nt 4.0 sp6 system).

              thanks!

              florent heyworth

              ------------------

              Comment


              • #8
                Hi Florent

                I seemed to be having a problem with it compiling. I am using PB DLL 6.00.
                Does not like the print statements:
                PRINT "Error: Could not find DNS server"
                PRINT "specify /d<DNS_Server_Address> ON the command LINE"
                So I changed them to MSGBOX statements.

                With PRINT to MSGBOX change, it compiles but I get "no data" when I run it with one
                email address, and get "Not implemented yet." when I run it with another. Not sure what
                that all means. Maybe I need to pick friends with better email addresses?

                I agree that the total "DNS finding" routine should look in all locations,
                and maybe eliminate duplicates. In my application, I'll ping them as well
                so that I have a list that I believe is active DNS servers. I tried to use the
                loadlibrary way of using iphlpapi.dll as, from what I can find about it,
                there are a lot of windows systems that don't have it at all, and it sounds
                from your experience that some machines may have it, but a variation that
                does not include GetNetworkParams(?) In those cases, I'll have to rely on
                the System Registry.

                I'll eventually have to make my application work on our testbed, which
                quad-boots Win 95 OSR-2, Win 98 SE, Win ME, and Win 2k Professional. As far
                as I know, Win 95 does not have iphlpapi.dll on it. I think 98 & Me do.
                Not sure about Win 2k, or if it does, if it supports GetNetworkParams.

                ------------------
                Michael Burns

                [This message has been edited by Michael Burns (edited May 16, 2001).]
                Michael Burns

                Comment


                • #9
                  Hi Michael

                  the app expects the following arguments.

                  <domain>|<mail address> /tMX [/d<optional dns server>]

                  /t represents the record type - at the moment only
                  MX (Mail Exchange records) are implemented

                  /d is an optional switch - you can use it to override the
                  DNS server look-up code telling it you want to use a
                  specific DNS server for the lookup. If this switch is not
                  present the program will try to look up the DNS server
                  using a combination GetNetworkParams and the registry.

                  So valid command lines would be:

                  dnsqry [email protected] /tMX
                  dnsqry domain.com /tMX
                  dnsqry domain.com /tMX /d193.12.1.25

                  When the program returns no data it means that the DNS server
                  could not answer the query you sent it. Did you try it with
                  a valid address?

                  Cheers

                  Florent


                  ------------------

                  Comment


                  • #10
                    FYI Florent, The necessary dll is installed on my NT4 SP6
                    + post SP6 hotfixes, I also have IE 5 installed. So I must have
                    gotten it in one of those "upgrades". MSDN suggests that it's
                    installed in a number of SP's and IE upgrades but I couldn't
                    determine which one actually was responsible for the installation
                    of the required dll. Haven't tried the utility yet but glad I was
                    able to point everyone in the right direction.

                    Comment


                    • #11
                      Hi John

                      thanks for the info. I'm running NT 4.0 with SP6a and iphlpapi.dll
                      is installed and GetNetworkParams is an exported function. However
                      it returns ERROR_NOT_SUPPORTED when called (it seems not to
                      be implemented). MSDN seems to indicate that GetNetworkParams
                      is only implemented on Win2000/Win98+.

                      Cheers

                      Florent

                      ------------------

                      Comment

                      Working...
                      X