2025-11-28 00:35:46 +09:00

335 lines
9.6 KiB
C

//+===================================================================
//
// This file is part of the Microsoft .NET Framework SDK Code Samples.
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//This source code is intended only as a supplement to Microsoft
//Development Tools and/or on-line documentation. See these other
//materials for detailed information regarding Microsoft code samples.
//
//THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//PARTICULAR PURPOSE.
//
// GetConnInfo.c
// Gets information about the active connections on the server. Prints the port on
// which the connection has been accepted on the server and the IPv4 and IPv6
// address that the client connection acquired.
//
//
//
//+===================================================================
#define MAX_IPV6_STRING 46
#define IPV6_INTERFACE_ID_LENGTH_IN_BYTES 8
//TODO: Need to uncomment this when nt.h is in SDK
/*
#include <nt.h> //included for RtlIpv6AddressToString
#include <ntrtl.h> //included for RtlIpv6AddressToString
#include <nturtl.h>//included for RtlIpv6AddressToString*/
#include <Ws2tcpip.h>
#include <windows.h>
#include <mprapi.h>
#include <wchar.h>
//#include <ws2ipdef.h>
//#include <Ws2tcpip.h> //included for IN6_ADDR
VOID
CopyPrefixBytes(
BYTE *Address,
BYTE* Prefix,
ULONG PrefixLength,
ULONG AddressBytes
)
//
//Routine Description:
//
// Copy an address prefix of the given length
//
//Arguments:
// Address - Supplies the address buffer to fill in.
// Prefix - Supplies the initial prefix.
// PrefixLength - Supplies the initial prefix length in bits.
// AddressBytes- Prefix length in bytes (ceiling)
//
{
ULONG PLBytes, PLRemainderBits, Loop;
PLBytes = PrefixLength / 8;
PLRemainderBits = PrefixLength % 8;
if (AddressBytes != (PLBytes+ (PLRemainderBits?1:0))) return;
for (Loop = 0; Loop < PLBytes; Loop++) {
Address[Loop] = Prefix[Loop];
}
if (PLRemainderBits ) {
Address[PLBytes] = (UCHAR)(Prefix[PLBytes] &
(0xff << (8 - PLRemainderBits)));
}
}
DWORD ConvertAddressToString(IN6_ADDR *ipv6addr,WCHAR * hoststring)
//
//Routine Description:
//
// Converts an IPv6 address in IN6_ADDR to a readable host string format
//
//Arguments:
// ipv6addr - Pointer to IN6_ADDR structure having the IPv6 address.
// hoststring - The buffer to be returned with the address in host string format.
//
{
struct sockaddr_in6 sin6;
int RetVal = 0;
DWORD dwRet = ERROR_SUCCESS;
WSADATA WsaData;
if(WSAStartup(0x202,&WsaData))
{
dwRet = GetLastError();
wprintf(L"Error in WSAStartup[Error:%d]\n",dwRet);
goto Cleanup;
}
sin6.sin6_family = AF_INET6;
sin6.sin6_port = 0;
sin6.sin6_flowinfo = 0;
sin6.sin6_scope_id = 0;
sin6.sin6_addr = *ipv6addr;
RetVal = GetNameInfoW((SOCKADDR *)&sin6,
sizeof(struct sockaddr_in6),
hoststring,
MAX_IPV6_STRING,
NULL,
0,
NI_NUMERICHOST);
if (RetVal != 0)
{
dwRet = WSAGetLastError();
wprintf(L"Could not convert IPv6 address to address string format![Error:%d]",dwRet);
}
Cleanup:
WSACleanup();
return dwRet;
}
int _cdecl wmain(int argc,WCHAR * argv[])
{
MPR_SERVER_HANDLE hMprServer = NULL; // Variable to hold the handle to the Server to be used in subsequent calls to the Router
HANDLE hConnection = NULL; //Handle to the client connection whose connection information we query
DWORD dwStatus = ERROR_SUCCESS;
DWORD dwLevel = 0;
LPBYTE lplpbBuffer = NULL; // Buffer to be used in MprAdminPortEnum to retrieve the information
LPBYTE lplpConnBuffer = NULL; // Buffer to be used in MprAdminConnectionGetInfo to get the information about a connection
DWORD dwEntriesRead = 0;
DWORD dwTotalEntries = 0;
DWORD dwResumeHandle = 0;
WCHAR * szErrorString = NULL;
PRAS_PORT_0 pRasPort = NULL;
int ActivePortCount = 0;
IN6_ADDR ipv6Address = {0}; // Variable to hold IPv6 address of the client connection
WCHAR szIpv6AddrString[MAX_IPV6_STRING] = {0}; //Variable to hold the IPv6 address string of the client connection
if (argc!=1 && argc!=2)
{
wprintf(L"Usage:\n");
wprintf(L"%s - For local machine\n",argv[0]);
wprintf(L"%s Hostname|IP address - For remote machine\n",argv[0]);
wprintf(L"If you specify a remote machine's hostname or IP address\n");
wprintf(L"here, you should ensure that you have administrative priveleges\n");
wprintf(L"to execute this program on the remote machine. For this you can\n");
wprintf(L"do a net use to the IPC$ on the machine before executing this program\n");
wprintf(L"For e.g. net use \\\\home-computer\\ipc$ \n");
dwStatus = -1;
goto Cleanup;
}
// Obtain a handle to the RRAS server using the API MprAdminServerConnect.
// This handle is used in all subsequest MPRAPI calls to the RRAS server.
if (argc == 1)
dwStatus = MprAdminServerConnect(NULL, &hMprServer);
else
dwStatus = MprAdminServerConnect(argv[1], &hMprServer);
if(dwStatus != ERROR_SUCCESS)
{
MprAdminGetErrorString(dwStatus,&szErrorString);
wprintf(L" MprAdminServerConnect failed with ERROR:[%d:%s]\n", dwStatus,szErrorString);
goto Cleanup;
}
dwLevel = 0;
// We enumerate all the ports on the RRAS server and use the information returned
// to find the connection information for the active ports
dwStatus = MprAdminPortEnum(hMprServer,
dwLevel,
INVALID_HANDLE_VALUE,
&lplpbBuffer,
(DWORD)-1,
&dwEntriesRead,
&dwTotalEntries,
&dwResumeHandle);
if(dwStatus != ERROR_SUCCESS)
{
MprAdminGetErrorString(dwStatus,&szErrorString);
wprintf(L"MprAdminPortEnum failed with ERROR:[%d:%s]\n",dwStatus,szErrorString);
goto Cleanup;
}
if ((dwEntriesRead != 0) && (lplpbBuffer != NULL))
{
PRAS_CONNECTION_3 pRasConnInfo = NULL;
DWORD i = 0;
pRasPort= (PRAS_PORT_0) (lplpbBuffer);
// Log the port information of the connection and get additional information for the connection
// using the connection handle returned in RAS_PORT_0 structure in the above call
for (i=0;i<(dwEntriesRead);i++)
{
if (pRasPort[i].dwPortCondition == RAS_PORT_AUTHENTICATED) // Try to get the connection information only for the active ports
{
ActivePortCount++;
hConnection = pRasPort[i].hConnection;
// Get the connection information for the active ports. dwLevel is set to 3 so that
// RAS_CONNECTION_3 structures are returned by the call
dwLevel = 3;
dwStatus = MprAdminConnectionGetInfo(hMprServer,dwLevel,hConnection,&lplpConnBuffer);
if(dwStatus != ERROR_SUCCESS)
{
MprAdminGetErrorString(dwStatus,&szErrorString);
wprintf(L"MprAdminConnectionGetInfo:FAIL with ERROR:[%d:%s]\n",dwStatus,szErrorString);
goto Cleanup;
}
pRasConnInfo = (PRAS_CONNECTION_3) (lplpConnBuffer);
//We print the information about the connection that we got
//from the call to MprAdminConnectionGetInfo
wprintf(L"User %s has connected on port %s for this connection\n",pRasConnInfo->wszUserName,pRasPort[i].wszPortName);
// For the IPv6 address of the client, we get the interface ID, the prefix and the prefix length
// from the RAS_CONNECTION_3 structure. Here we copy the prefix and the 64-bit interface
// ID to a IN6_ADDR structure and use GetNameInfoW with the flag NI_NUMERICHOST to convert it to
// IPv6 address string in the readable form
//
// As the prefix length we get from the structure is in bits we need the 'CopyPrefixBytes'
// module to convert the length into bytes and copy the prefix accordingly.
CopyPrefixBytes(ipv6Address.u.Byte,
pRasConnInfo->PppInfo3.ipv6.bPrefix,
pRasConnInfo->PppInfo3.ipv6.dwPrefixLength,
sizeof(ipv6Address)-IPV6_INTERFACE_ID_LENGTH_IN_BYTES);
// Copy the RemoteInterfaceIdentifier to the last 8 bytes of ipv6Address.u.Byte
memcpy(&ipv6Address.u.Byte[IPV6_INTERFACE_ID_LENGTH_IN_BYTES],
pRasConnInfo->PppInfo3.ipv6.bRemoteInterfaceIdentifier,
IPV6_INTERFACE_ID_LENGTH_IN_BYTES);
// Convert the IPv6 address in IN6_ADDR to a readable IPv6 address string
dwStatus = ConvertAddressToString(&ipv6Address,szIpv6AddrString);
if (dwStatus == ERROR_SUCCESS)
wprintf(L"IPv6 address of the client: %s\n",szIpv6AddrString);
wprintf(L"IPv4 address of the client: %s\n",pRasConnInfo->PppInfo3.ip.wszRemoteAddress);
MprAdminBufferFree(lplpConnBuffer);
lplpConnBuffer = NULL;
}
}
}
if (ActivePortCount !=0 )
wprintf(L"Successfully retrieved the connection information!\n");
else
{
wprintf(L"No active connections on the server!\n");
wprintf(L"Make a connection to this server and try running the program again\n");
dwStatus = -1;
}
//cleanup
Cleanup:
wprintf(L"Exiting....\n");
if (szErrorString)
MprAdminBufferFree(szErrorString);
if (lplpbBuffer)
MprAdminBufferFree(lplpbBuffer);
if (lplpConnBuffer)
MprAdminBufferFree(lplpConnBuffer);
return dwStatus;
}