Page 1 of 1
How can I retrieve the netcard gateway?
Posted: Fri Mar 08, 2024 9:07 pm
by Armoured
On the German section of the forum, I came across the following post:
https://www.purebasic.fr/german/viewtop ... 15#p258815
In this example, the network card's gateway is not being returned. How can one retrieve it? Additionally, I've noticed that the "IP_ADAPTER_GATEWAY_ADDRESS_LH" structure seems to be missing, which I believe is intended for this purpose.
Could you provide me with an example that includes it? I attempted to post in the German forum, but encountered difficulties in doing so.
Thanks.
Re: How can I retrieve the netcard gateway?
Posted: Fri Mar 08, 2024 10:17 pm
by HeX0R
That code is pretty old, and also not complete.
Since I have no more use for it, I'm not willing to update it for a complete usage of GetAdaptersAddresses(), but you can try forcing it to use the old way by:
Re: How can I retrieve the netcard gateway?
Posted: Fri Mar 08, 2024 11:10 pm
by Armoured
Hi,
Unfortunately, the issue persists and it's still not possible to retrieve the gateway.
In my version, I've implemented these structures. Can you tell me if they seem valid to you?
Code: Select all
Structure IP_ADAPTER_ADDRESSES
Length.l ; unsigned
IfIndex.l
*Next.IP_ADAPTER_ADDRESSES
*AdapterName
*FirstUnicastAddress;.PIP_ADAPTER_UNICAST_ADDRESS
*FirstAnycastAddress;.PIP_ADAPTER_ANYCAST_ADDRESS
*FirstMulticastAddress;.PIP_ADAPTER_MULTICAST_ADDRESS
*FirstDnsServerAddress;.PIP_ADAPTER_DNS_SERVER_ADDRESS
*DnsSuffix ;.PWCHAR
*Description ;.PWCHAR
*FriendlyName ;.PWCHAR
PhysicalAddress.b [#MAX_ADAPTER_ADDRESS_LENGTH]
PhysicalAddressLength.l
Flags.l
Mtu.l
IfType.l
OperStatus.l
Ipv6IfIndex.l
ZoneIndices.l [16]
*FirstPrefix;.PIP_ADAPTER_PREFIX
;Le successive voci sono state aggiunte da me per ricavare il gateway
TransmitLinkSpeed.q
ReceiveLinkSpeed.q
*FirstWinsServerAddress;PIP_ADAPTER_WINS_SERVER_ADDRESS_LH
*FirstGatewayAddress;PIP_ADAPTER_GATEWAY_ADDRESS_LH
EndStructure
Structure SOCKET_ADDRESS
*lpSockaddr
iSockaddrLength.l
EndStructure
Structure IP_ADAPTER_GATEWAY_ADDRESS_LH
Length.l
Reserved.l
*Next.IP_ADAPTER_GATEWAY_ADDRESS_LH
Address.SOCKET_ADDRESS
EndStructure
Thanks.
Re: How can I retrieve the netcard gateway?
Posted: Fri Mar 08, 2024 11:14 pm
by HeX0R
Armoured wrote: Fri Mar 08, 2024 11:10 pm
Hi,
Unfortunately, the issue persists and it's still not possible to retrieve the gateway.
You might have to add #GAA_FLAG_INCLUDE_GATEWAYS to the *THIS\GetAdaptersAddresses() call (in IFNA_Refresh())
Re: How can I retrieve the netcard gateway?
Posted: Fri Mar 08, 2024 11:22 pm
by idle
Re: How can I retrieve the netcard gateway?
Posted: Sat Mar 09, 2024 2:37 am
by Armoured
I tried to simplify as much as possible to be able to post an example here. What I would expect to get is a decimal version of the Gateway IP, but unfortunately, I only get a memory access error. What am I doing wrong? Do you have any suggestions to offer? Thank you.
Code: Select all
#IF_TYPE_ETHERNET_CSMACD = 6
#MAX_ADAPTER_ADDRESS_LENGTH = 8
#GAA_FLAG_INCLUDE_GATEWAYS = 128 ;$0080
#ERROR_ADDRESS_NOT_ASSOCIATED = 1228
Structure MIB_IPADDRROW
dwAddr.l
dwIndex.l
dwMask.l
dwBCastAddr.l
dwReasmSize.l
unused1.w
wType.w
EndStructure
Structure MIB_IPADDRTABLE
dwNumEntries.l
*ips.MIB_IPADDRROW
EndStructure
Structure SOCKET_ADDRESS
*lpSockaddr
iSockaddrLength.l
EndStructure
Structure IP_ADAPTER_PREFIX
; union { ULONGLONG Alignment; struct { ULONG Length; DWORD Flags; } ; } ;
Length.l
Flags.l
*Next.IP_ADAPTER_PREFIX
Address.SOCKET_ADDRESS
PrefixLength.l
EndStructure
Structure IP_ADAPTER_GATEWAY_ADDRESS_LH
; union { ULONGLONG Alignment; struct { ULONG Length; DWORD Flags; } ; } ;
Length.l
Reserved.l
*Next.IP_ADAPTER_GATEWAY_ADDRESS_LH
Address.SOCKET_ADDRESS
EndStructure
Structure IP_ADAPTER_ADDRESSES
Length.l ; unsigned
IfIndex.l
*Next.IP_ADAPTER_ADDRESSES
*AdapterName
*FirstUnicastAddress;.PIP_ADAPTER_UNICAST_ADDRESS
*FirstAnycastAddress;.PIP_ADAPTER_ANYCAST_ADDRESS
*FirstMulticastAddress;.PIP_ADAPTER_MULTICAST_ADDRESS
*FirstDnsServerAddress;.PIP_ADAPTER_DNS_SERVER_ADDRESS
*DnsSuffix ;.PWCHAR
*Description ;.PWCHAR
*FriendlyName ;.PWCHAR
PhysicalAddress.b [#MAX_ADAPTER_ADDRESS_LENGTH]
PhysicalAddressLength.l
Flags.l
Mtu.l
IfType.l
OperStatus.l
Ipv6IfIndex.l
ZoneIndices.l [16]
*FirstPrefix;.PIP_ADAPTER_PREFIX
TransmitLinkSpeed.q
ReceiveLinkSpeed.q
*FirstWinsServerAddress;PIP_ADAPTER_WINS_SERVER_ADDRESS_LH
*FirstGatewayAddress;PIP_ADAPTER_GATEWAY_ADDRESS_LH
EndStructure
Procedure ListIPs()
Protected dll = OpenLibrary(#PB_Any, "iphlpapi.dll")
Protected tablesize = SizeOf(IP_ADAPTER_ADDRESSES)
Protected *table.IP_ADAPTER_ADDRESSES = AllocateMemory(tablesize)
Protected *info.IP_ADAPTER_ADDRESSES
Protected valid = #False
;Variabili per la parte che scorre i vari IP associati alle schede di rete
Protected iptablesize = SizeOf(MIB_IPADDRTABLE)
Protected *iptable.MIB_IPADDRTABLE = AllocateMemory(iptablesize)
Protected *ipinfo.MIB_IPADDRROW
Protected interfaceindex
Protected ipvalid = #False
Protected loop.l
If (dll)
Define GetAdaptersAddresses = GetFunction(dll, "GetAdaptersAddresses")
If (GetAdaptersAddresses)
Repeat
Select CallFunctionFast(GetAdaptersAddresses, #AF_INET, #GAA_FLAG_INCLUDE_GATEWAYS, #Null, *table, @tablesize)
Case #NO_ERROR
; Can exit loop now...
valid = #True
Case #ERROR_ADDRESS_NOT_ASSOCIATED
If IsLibrary(dll)
CloseLibrary(dll)
EndIf
FreeMemory(*table)
ProcedureReturn
Case #ERROR_BUFFER_OVERFLOW
; Increase buffer size and try again...
*table = ReAllocateMemory(*table, tablesize)
Default
If IsLibrary(dll)
CloseLibrary(dll)
EndIf
FreeMemory(*table)
ProcedureReturn
EndSelect
Until valid
EndIf
EndIf
*info.IP_ADAPTER_ADDRESSES = *table
While *info
Select *info\ifType
;La scheda è Ethernet
Case #IF_TYPE_ETHERNET_CSMACD
;se l'interfaccia è in funzione e in grado di trasmettere e ricevere
If (*info\OperStatus = 1)
Repeat
Select GetIpAddrTable_(*iptable, @iptablesize, #True)
Case #NO_ERROR
ipvalid = #True
Case #ERROR_INSUFFICIENT_BUFFER
*iptable = ReAllocateMemory (*iptable, iptablesize)
EndSelect
Until ipvalid
*ipinfo.MIB_IPADDRROW = @*iptable\ips
For loop = 0 To *iptable\dwNumEntries - 1
interfaceindex = *ipinfo\dwIndex
If interfaceindex > 0
If (interfaceindex = *info\IfIndex)
Debug "Description: " + PeekS(*table\Description, -1, #PB_Unicode) + #CRLF$
Define *gatewaylist.IP_ADAPTER_GATEWAY_ADDRESS_LH = *info\FirstGatewayAddress
Define *gateway.SOCKET_ADDRESS = *gatewaylist\Address
Debug "Gateway: " + Str(PeekQ(*gateway\lpSockaddr)) ;I have a memory access error here
EndIf
EndIf
*ipinfo = *ipinfo + SizeOf (MIB_IPADDRROW)
Next loop
EndIf
EndSelect
*info = *info\Next
Wend
FreeMemory(*iptable)
FreeMemory(*table)
EndProcedure
ListIPs()
Re: How can I retrieve the netcard gateway?
Posted: Sat Mar 09, 2024 3:00 am
by idle
doesn't my code above print the gateway ?
Name {0CA112EB-9D58-4953-A09A-A3EFFC0CB6E9}
Description Intel(R) Wi-Fi 6 AX200 160MHz
DHCP 1
Address 192.168.1.2
Mask 255.255.255.0
Gateway 192.168.1.1
Index 3
mac address A4:EF:C8:BE:3C:2D
DHCP: LeaseObtained 09.03.2024 11:39:21
DHCP: LeaseExpires 10.03.2024 11:39:21
DNS servers list
127.0.0.1
1.1.1.1
Re: How can I retrieve the netcard gateway?
Posted: Sat Mar 09, 2024 3:13 am
by Armoured
idle wrote: Sat Mar 09, 2024 3:00 am
doesn't my code above print the gateway ?
Name {0CA112EB-9D58-4953-A09A-A3EFFC0CB6E9}
Description Intel(R) Wi-Fi 6 AX200 160MHz
DHCP 1
Address 192.168.1.2
Mask 255.255.255.0
Gateway 192.168.1.1
Index 3
mac address A4:EF:C8:BE:3C:2D
DHCP: LeaseObtained 09.03.2024 11:39:21
DHCP: LeaseExpires 10.03.2024 11:39:21
DNS servers list
127.0.0.1
1.1.1.1
Yes, yours correctly displays the gateway, but it doesn't use GetAdaptersAddresses, and this would force me to rewrite a large part of my code.
Re: How can I retrieve the netcard gateway?
Posted: Sat Mar 09, 2024 5:12 am
by idle
I'm a bit fatigued, it's almost there
Code: Select all
EnumerationBinary IP_ADAPTER_ADDRESSES_Flags
#DdnsEnabled=1
#RegisterAdapterSuffix
#Dhcpv4Enabled
#ReceiveOnly
#NoMulticast
#Ipv6OtherStatefulConfig
#NetbiosOverTcpipEnabled
#Ipv4Enabled
#Ipv6Enabled
#Ipv6ManagedAddressConfigurationSupported
EndEnumeration
#IF_TYPE_ETHERNET_CSMACD = 6
#MAX_ADAPTER_ADDRESS_LENGTH=8
#MAX_DHCPV6_DUID_LENGTH=16
#ERROR_ADDRESS_NOT_ASSOCIATED = 1228
#GAA_FLAG_INCLUDE_GATEWAYS = $80
Structure MIB_IPADDRROW
dwAddr.l
dwIndex.l
dwMask.l
dwBCastAddr.l
dwReasmSize.l
unused1.w
wType.w
EndStructure
Structure MIB_IPADDRTABLE
dwNumEntries.l
*ips.MIB_IPADDRROW
EndStructure
Structure SOCKET_ADDRESS
*lpSockaddr;
iSockaddrLength.l;
EndStructure
Structure IP_ADAPTER_ADDRESSES_LH
StructureUnion
Length.q;
IfIndex.l;
EndStructureUnion;
*next.IP_ADAPTER_ADDRESSES_LH
*AdapterName;
*FirstUnicastAddress;.PIP_ADAPTER_UNICAST_ADDRESS_LH ;
*FirstAnycastAddress;.PIP_ADAPTER_ANYCAST_ADDRESS_XP;
*FirstMulticastAddress;.PIP_ADAPTER_MULTICAST_ADDRESS_XP;
*FirstDnsServerAddress;.PIP_ADAPTER_DNS_SERVER_ADDRESS_XP;
DnsSuffix.s;
Description.s;
FriendlyName.s;
PhysicalAddress.a[#MAX_ADAPTER_ADDRESS_LENGTH];
PhysicalAddressLength.l;
Flags.l; enum IP_ADAPTER_ADDRESSES_Flags bitfield
Mtu.l;
IfType.l;IFTYPE
OperStatus.l;IF_OPER_STATUS ;
Ipv6IfIndex.l;IF_INDEX ;
ZoneIndices.l[16];
*FirstPrefix;.PIP_ADAPTER_PREFIX_XP;
TransmitLinkSpeed.q;
ReceiveLinkSpeed.q;
*FirstWinsServerAddress;.PIP_ADAPTER_WINS_SERVER_ADDRESS_LH;
*FirstGatewayAddress;.PIP_ADAPTER_GATEWAY_ADDRESS_LH;
Ipv4Metric.l;
Ipv6Metric.l;
Luid.l;IF_LUID;
Dhcpv4Server.SOCKET_ADDRESS;
CompartmentId.l;NET_IF_COMPARTMENT_ID;
NetworkGuid.l;NET_IF_NETWORK_GUID;
ConnectionType.l;NET_IF_CONNECTION_TYPE ;
TunnelType.l;TUNNEL_TYPE;
Dhcpv6Server.SOCKET_ADDRESS ;
Dhcpv6ClientDuid.a[#MAX_DHCPV6_DUID_LENGTH];
Dhcpv6ClientDuidLength.l;
Dhcpv6Iaid.l;
*FirstDnsSuffix;.PIP_ADAPTER_DNS_SUFFIX ;
EndStructure
Structure IP_ADAPTER_GATEWAY_ADDRESS_LH
; union { ULONGLONG Alignment; struct { ULONG Length; DWORD Flags; } ; } ;
StructureUnion
Length.q
Reserved.l
EndStructureUnion
*Next.IP_ADAPTER_GATEWAY_ADDRESS_LH
Address.SOCKET_ADDRESS
EndStructure
ImportC "iphlpapi.lib"
GetAdaptersAddresses(Family.l,Flags.l,*Reserved,*AdapterAddresses,*SizePointer)
EndImport
Procedure ListIPs()
Protected *table.IP_ADAPTER_ADDRESSES_LH = AllocateMemory(SizeOf(IP_ADAPTER_ADDRESSES_LH))
Protected tablesize = SizeOf(IP_ADAPTER_ADDRESSES_LH)
Protected iptablesize = SizeOf(MIB_IPADDRTABLE)
Protected *iptable.MIB_IPADDRTABLE = AllocateMemory(iptablesize)
Protected *ipinfo.MIB_IPADDRROW
Repeat
Select GetAdaptersAddresses(#AF_INET, #GAA_FLAG_INCLUDE_GATEWAYS, #Null, *table, @tablesize)
Case #NO_ERROR
; Can exit loop now...
valid = #True
Case #ERROR_ADDRESS_NOT_ASSOCIATED
FreeMemory(*table)
ProcedureReturn
Case #ERROR_BUFFER_OVERFLOW
; Increase buffer size and try again...
*table = ReAllocateMemory(*table, tablesize)
Default
FreeMemory(*table)
ProcedureReturn
EndSelect
Until valid
If *table
*info.IP_ADAPTER_ADDRESSES_LH = *table
While *info
Select *info\ifType
;La scheda è Ethernet
Case #IF_TYPE_ETHERNET_CSMACD,71
;se l'interfaccia è in funzione e in grado di trasmettere e ricevere
If (*info\OperStatus = 1)
Repeat
Select GetIpAddrTable_(*iptable, @iptablesize, #True)
Case #NO_ERROR
ipvalid = #True
Case #ERROR_INSUFFICIENT_BUFFER
*iptable = ReAllocateMemory (*iptable, iptablesize)
EndSelect
Until ipvalid
*ipinfo.MIB_IPADDRROW = @*iptable\ips
For loop = 0 To *iptable\dwNumEntries - 1
interfaceindex = *ipinfo\dwIndex
If interfaceindex > 0
;If (interfaceindex = *info\IfIndex)
Debug "Description: " + *info\Description + #CRLF$
Define *gatewaylist.IP_ADAPTER_GATEWAY_ADDRESS_LH = *info\FirstGatewayAddress
Define *gateway.SOCKET_ADDRESS = *gatewaylist\Address
Debug "Gateway: " + Str(*gateway\lpSockaddr) ;I have a memory access error here
;EndIf
EndIf
*ipinfo = *ipinfo + SizeOf (MIB_IPADDRROW)
Next loop
EndIf
EndSelect
*info = *info\Next
Wend
FreeMemory(*iptable)
FreeMemory(*table)
EndIf
EndProcedure
ListIPs()
Re: How can I retrieve the netcard gateway?
Posted: Sat Mar 09, 2024 11:09 am
by breeze4me
Try this.
Code: Select all
#IF_TYPE_ETHERNET_CSMACD = 6
#IF_TYPE_IEEE80211 = 71
#MAX_ADAPTER_ADDRESS_LENGTH = 8
#GAA_FLAG_INCLUDE_GATEWAYS = 128 ;$0080
#ERROR_ADDRESS_NOT_ASSOCIATED = 1228
Structure MIB_IPADDRROW
dwAddr.l
dwIndex.l
dwMask.l
dwBCastAddr.l
dwReasmSize.l
unused1.w
wType.w
EndStructure
Structure MIB_IPADDRTABLE
dwNumEntries.l
*ips.MIB_IPADDRROW
EndStructure
Structure SOCKET_ADDRESS
*lpSockaddr.SOCKADDR_IN
iSockaddrLength.l
EndStructure
Structure IP_ADAPTER_PREFIX
; union { ULONGLONG Alignment; struct { ULONG Length; DWORD Flags; } ; } ;
Length.l
Flags.l
*Next.IP_ADAPTER_PREFIX
Address.SOCKET_ADDRESS
PrefixLength.l
EndStructure
Structure IP_ADAPTER_GATEWAY_ADDRESS_LH
; union { ULONGLONG Alignment; struct { ULONG Length; DWORD Flags; } ; } ;
Length.l
Reserved.l
*Next.IP_ADAPTER_GATEWAY_ADDRESS_LH
Address.SOCKET_ADDRESS
EndStructure
Structure IP_ADAPTER_ADDRESSES
Length.l ; unsigned
IfIndex.l
*Next.IP_ADAPTER_ADDRESSES
*AdapterName
*FirstUnicastAddress;.PIP_ADAPTER_UNICAST_ADDRESS
*FirstAnycastAddress;.PIP_ADAPTER_ANYCAST_ADDRESS
*FirstMulticastAddress;.PIP_ADAPTER_MULTICAST_ADDRESS
*FirstDnsServerAddress;.PIP_ADAPTER_DNS_SERVER_ADDRESS
*DnsSuffix ;.PWCHAR
*Description ;.PWCHAR
*FriendlyName ;.PWCHAR
PhysicalAddress.b [#MAX_ADAPTER_ADDRESS_LENGTH]
PhysicalAddressLength.l
Flags.l
Mtu.l
IfType.l
OperStatus.l
Ipv6IfIndex.l
ZoneIndices.l [16]
*FirstPrefix;.PIP_ADAPTER_PREFIX
TransmitLinkSpeed.q
ReceiveLinkSpeed.q
*FirstWinsServerAddress;PIP_ADAPTER_WINS_SERVER_ADDRESS_LH
*FirstGatewayAddress;PIP_ADAPTER_GATEWAY_ADDRESS_LH
EndStructure
Procedure ListIPs()
Protected dll = OpenLibrary(#PB_Any, "iphlpapi.dll")
Protected GetAdaptersAddresses
Protected tablesize
Protected *table.IP_ADAPTER_ADDRESSES
Protected *info.IP_ADAPTER_ADDRESSES
;Variabili per la parte che scorre i vari IP associati alle schede di rete
Protected iptablesize
Protected *iptable.MIB_IPADDRTABLE
Protected *ipinfo.MIB_IPADDRROW
Protected interfaceindex
Protected loop.l
Protected *gatewaylist.IP_ADAPTER_GATEWAY_ADDRESS_LH
Protected *str
Protected Result
If (dll)
GetAdaptersAddresses = GetFunction(dll, "GetAdaptersAddresses")
If (GetAdaptersAddresses)
If CallFunctionFast(GetAdaptersAddresses, #AF_INET, #GAA_FLAG_INCLUDE_GATEWAYS, #Null, 0, @tablesize) = #ERROR_BUFFER_OVERFLOW
If tablesize > 0
*table = AllocateMemory(tablesize)
If *table
If CallFunctionFast(GetAdaptersAddresses, #AF_INET, #GAA_FLAG_INCLUDE_GATEWAYS, #Null, *table, @tablesize) = #NO_ERROR
Result = 1
EndIf
EndIf
EndIf
EndIf
EndIf
EndIf
If Result = 0 : Goto Proc_Exit : EndIf
Result = 0
If GetIpAddrTable_(0, @iptablesize, #True) = #ERROR_INSUFFICIENT_BUFFER
If iptablesize > 0
*iptable = AllocateMemory(iptablesize)
If *iptable
If GetIpAddrTable_(*iptable, @iptablesize, #True) = #NO_ERROR
Result = 1
EndIf
EndIf
EndIf
EndIf
If Result = 0 : Goto Proc_Exit : EndIf
*info = *table
While *info
Select *info\ifType
Case #IF_TYPE_ETHERNET_CSMACD, #IF_TYPE_IEEE80211
;se l'interfaccia è in funzione e in grado di trasmettere e ricevere
If (*info\OperStatus = 1)
*ipinfo = @*iptable\ips
If *ipinfo = 0 : Break : EndIf
For loop = 0 To *iptable\dwNumEntries - 1
interfaceindex = *ipinfo\dwIndex
If interfaceindex > 0
If (interfaceindex = *info\IfIndex)
If *info\FirstGatewayAddress = 0 : Continue : EndIf
If *info\Description
Debug "Description: " + PeekS(*info\Description, -1, #PB_Unicode)
EndIf
*gatewaylist = *info\FirstGatewayAddress
If *gatewaylist And *gatewaylist\Address\lpSockaddr\sin_addr
*str = inet_ntoa_(*gatewaylist\Address\lpSockaddr\sin_addr)
If *str
Debug "Gateway: " + PeekS(*str, -1, #PB_Ascii)
EndIf
EndIf
EndIf
EndIf
*ipinfo = *ipinfo + SizeOf (MIB_IPADDRROW)
Next loop
EndIf
EndSelect
*info = *info\Next
Wend
Proc_Exit:
If *iptable : FreeMemory(*iptable) : EndIf
If *table : FreeMemory(*table) : EndIf
If dll : CloseLibrary(dll) : EndIf
EndProcedure
ListIPs()
Re: How can I retrieve the netcard gateway?
Posted: Sat Mar 09, 2024 7:53 pm
by Armoured
Thank you breeze4me, your code has been very helpful! I also wanted to thank idle and HeX0R for their contributions.
