Francois PIETTE wrote:
>>> Searching MSDN for SIO_GET_INTERFACE_LIST report a few hits. But
>>> WSAIoctl doesn't lit it !
>>
>> Thanks I'll investigate more in this, my idea was to incude an
>> utility function something like IsSameSubnet(IP: TInAddr): Boolean in
>> WSocket.pas provided that it must not use IpHlpApi, supported by
>> Winsock/WSocket.pas only.
>
> OK. I think it is important that TWSocket doesn't depend on IpHlpApi.
> Anything needed from this API should be encapsulated in another
> object which could optionnaly linked to TWSocket if the user need
> that feature. The component should continue to work without need for
> additional API.
Concerning SIO_GET_INTERFACE_LIST and WSAIoctl I found this at M$:
"Note Support of this command is mandatory for Windows Sockets
2-compliant TCP/IP service providers."
Also some websites claim that it works in Win98/ME/2K and 95 OSR2,
and NT srv pack #3. So what about having the stuff below included
in WSocket.pas? As you can see it is a lot due to missing Winsock2
stuff in both Delphi and ICS.
const
..
{ AG block added }
{$EXTERNALSYM SIO_GET_INTERFACE_LIST}
SIO_GET_INTERFACE_LIST = $4004747F;
{$EXTERNALSYM IFF_UP}
IFF_UP = $00000001;
{$EXTERNALSYM IFF_BROADCAST}
IFF_BROADCAST = $00000002;
{$EXTERNALSYM IFF_LOOPBACK}
IFF_LOOPBACK = $00000004;
{$EXTERNALSYM IFF_POINTTOPOINT}
IFF_POINTTOPOINT = $00000008;
{$EXTERNALSYM IFF_MULTICAST}
IFF_MULTICAST = $00000010;
type
{$EXTERNALSYM sockaddr}
sockaddr = record
sa_family : u_short; // address family
sa_data : array [0..13] of Char; // up to 14 bytes of direct
address
end;
{$EXTERNALSYM in6_addr}
in6_addr = record
case Integer of
0: (Byte : array [0..15] of u_char);
1: (Word : array [0..7] of u_short);
2: (s6_bytes : array [0..15] of u_char);
3: (s6_addr : array [0..15] of u_char);
4: (s6_words : array [0..7] of u_short);
end;
TIn6Addr = in6_addr;
PIn6Addr = ^in6_addr;
{$EXTERNALSYM sockaddr_in6_old}
sockaddr_in6_old = record
sin6_family : short; // AF_INET6
sin6_port : u_short; // Transport level port number
sin6_flowinfo : u_long; // IPv6 flow information
sin6_addr : in6_addr; // IPv6 address
end;
TSockAddrIn6Old = sockaddr_in6_old;
PSockAddrIn6Old = ^sockaddr_in6_old;
{$EXTERNALSYM sockaddr_gen}
sockaddr_gen = record
case Integer of
0: (Address : sockaddr);
1: (AddressIn : sockaddr_in);
2: (AddressIn6 : sockaddr_in6_old);
end;
TSockAddrGen = sockaddr_gen;
PSockAddrGen = ^sockaddr_gen;
{$EXTERNALSYM _INTERFACE_INFO}
_INTERFACE_INFO = record
iiFlags : u_long; // Interface flags
iiAddress : sockaddr_gen; // Interface address
iiBroadcastAddress : sockaddr_gen; // Broadcast address
iiNetmask : sockaddr_gen; // Network mask
end;
{$EXTERNALSYM INTERFACE_INFO}
INTERFACE_INFO = _INTERFACE_INFO;
TInterfaceInfo = INTERFACE_INFO;
PInterfaceInfo = ^INTERFACE_INFO;
{ AG block end }
function WSocketIsAddrInSubNet(saddr : TInAddr) : Boolean;
var
NumInterfaces : Integer;
BytesReturned : Cardinal;
PBuf : PChar;
P : PChar;
I : Integer;
Err : Integer;
BufSize : Cardinal;
iInfo : TInterfaceInfo;
s : TSocket;
begin
Result := FALSE;
BufSize := 20 * SizeOf(TInterfaceInfo);
GetMem(PBuf, BufSize);
try
s := WSocket_Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (s = INVALID_SOCKET) then
raise ESocketException.Create('Socket creation failed');
try
while True do
begin
Err := WSocket_WSAIoCtl(s, SIO_GET_INTERFACE_LIST, nil, 0,
PBuf, BufSize, BytesReturned,
nil, nil);
if Err = SOCKET_ERROR then
Err := WSocket_WSAGetLastError;
case Err of
0 : Break;
WSAEFAULT :
begin
// How many interfaces are allowed ??
// No chance to get correct buffer size w/o probing
if BufSize > 10000 * SizeOf(TInterfaceInfo) then
raise ESocketException.Create('Too many
interfaces');
Inc(BufSize, 100 * SizeOf(TInterfaceInfo));
FreeMem(PBuf);
GetMem(PBuf, BufSize);
end;
else
raise Exception.Create(SysErrorMessage(Err));
end;
end;
finally
WSocket_closesocket(S);
end;
P := PBuf;
NumInterfaces := BytesReturned div SizeOf(TInterfaceInfo);
for I := 0 to NumInterfaces - 1 do
begin
iInfo := PInterfaceInfo(P)^;
if (iInfo.iiAddress.addressIn.sin_addr.S_addr and
iInfo.iiNetMask.addressIn.sin_addr.S_addr) =
(saddr.S_addr and iInfo.iiNetMask.addressIn.sin_addr.S_addr) then
begin
Result := TRUE;
Exit;
end;
Inc(P, SizeOf(TInterfaceInfo));
end;
finally
FreeMem(PBuf);
end;
end;
--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://www.elists.org/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be