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

Reply via email to