Seite 1 von 2

GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 14:42
von GPI
Ich versuche Gerade GetIfTable2 zum laufen zu bringen.

hier die infos von MS:
http://msdn.microsoft.com/en-us/library ... 85%29.aspx
hier die Strucktur:
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Ich hab folgendes bisher gemacht:

Code: Alles auswählen

Global library
library=OpenLibrary(1,"Iphlpapi.dll")
Procedure GetIfTable2(a)
  ProcedureReturn CallFunction(1,"GetIfTable2",a)  
EndProcedure
Procedure  FreeMibTable(a)
  ProcedureReturn CallFunction(1,"FreeMibTable",a)    
EndProcedure

#IF_MAX_STRING_SIZE    = 256
#IF_MAX_PHYS_ADDRESS_LENGTH =32

Structure MIB_IF_ROW2 
  InterfaceLuid.b[8] ; Ein Quad 
   
  InterfaceIndex.l
  InterfaceGuid.b[4+2+2+8]
  Alias.u[#IF_MAX_STRING_SIZE +1];
  Description.u[#IF_MAX_STRING_SIZE +1];
  PhysicalAddressLength.l;
  PhysicalAddress.b[#IF_MAX_PHYS_ADDRESS_LENGTH];
  PermanentPhysicalAddress.b[#IF_MAX_PHYS_ADDRESS_LENGTH];
  Mtu.l;
  Type.l;
  TunnelType.l;?
  MediaType.l;?
  PhysicalMediumType.l;?
  AccessType.l;?
  DirectionType.l;?
  InterfaceAndOperStatusFlags.l
;   #struct {
;     BOOLEAN HardwareInterface  :1;
;     BOOLEAN FilterInterface  :1;
;     BOOLEAN ConnectorPresent   :1;
;     BOOLEAN NotAuthenticated  :1;
;     BOOLEAN NotMediaConnected  :1;
;     BOOLEAN Paused  :1;
;     BOOLEAN LowPower  :1;
;     BOOLEAN EndPointInterface  :1;
;   } InterfaceAndOperStatusFlags;
  OperStatus.l;
  AdminStatus.l;
  MediaConnectState.l;
  NetworkGuid.b[4+2+2+8];
  ConnectionType.l;
  TransmitLinkSpeed.q;
  ReceiveLinkSpeed.q;
  InOctets.q;
  InUcastPkts.q;
  InNUcastPkts.q;
  InDiscards.q;
  InErrors.q;
  InUnknownProtos.q;
  InUcastOctets.q;
  InMulticastOctets.q;
  InBroadcastOctets.q;
  OutOctets.q;
  OutUcastPkts.q;
  OutNUcastPkts.q;
  OutDiscards.q;
  OutErrors.q;
  OutUcastOctets.q;
  OutMulticastOctets.q;
  OutBroadcastOctets.q;
  OutQLen.q;
  fill.l; <--- Strucktur ist um 4 zu klein, aber wo?
EndStructure

buf.l
If GetIfTable2(@buf)=#ERROR_SUCCESS
  count=PeekL(buf)
  Debug PeekL(buf)
  Debug PeekL(buf+4)
  Debug PeekQ(buf)
  Debug "Anzahl:"+Str(count)  
  *line.mib_if_row2=buf+8;<- eigentlich müßte es+4 heißen, aber dann stimmt was nicht!
  For i=1 To count
    Debug "index:"+Str(*line\InterfaceIndex)
    ;Debug @*line\InterfaceIndex-*line
    Debug PeekS(@*line\Description,#IF_MAX_STRING_SIZE,#PB_Unicode)
    Debug PeekS(@*line\Alias,#IF_MAX_STRING_SIZE,#PB_Unicode)
    a$=""
    For b=0 To *line\PhysicalAddressLength-1
      a$+Hex(*line\PhysicalAddress[b] &$FF)
    Next
    ;Debug a$
    b=4
    a=PeekQ(@*line\inOctets+b)
    Debug Str(b)+"x:"+Hex(a)+" "+Str(a)

    
    *line+SizeOf(mib_if_row2)  
  Next
EndIf

    

FreeMibTable(buf)
Ja ist schlampig gemacht ;9

Meine Fragen:
Die Strucktur - irgendwo ist noch ein großer Fehler drin. die ist 4 Bytes zu klein.

Das zweite Problem: Das Datenfeld beginnt bei mir irgendwie 4 Bytes zu weit unten - ansonsten gibt Index bspw. völlig unsinige Werte. Aber InterfaceLuid ist definitv 8 Bytes groß - also kann ich nicht beide Probleme koppeln, wenn ich InterfaceLuid 4 Bytes größer mach.

Hat jemand eine Ahnung, wo mein Denkfehler ist?

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 14:49
von STARGÅTE
Vermutung:

Code: Alles auswählen

  InterfaceAndOperStatusFlags.l
;   #struct {
;     BOOLEAN HardwareInterface  :1;
;     BOOLEAN FilterInterface  :1;
;     BOOLEAN ConnectorPresent   :1;
;     BOOLEAN NotAuthenticated  :1;
;     BOOLEAN NotMediaConnected  :1;
;     BOOLEAN Paused  :1;
;     BOOLEAN LowPower  :1;
;     BOOLEAN EndPointInterface  :1;
;   } InterfaceAndOperStatusFlags;
Wieso hast du das auskommentiert ...
scheinbar hat doch InterfaceAndOperStatusFlags eine "Unterstruktur" mit 8 Booleans also Byte ?
somit wäre wenn überhaupt InterfaceAndOperStatusFlags.q richtig aber nicht .l ...
dort wäre also schon mal die 4 Bytes die fehlen...
Und es müsste dann InterfaceAndOperStatusFlags.InterfaceAndOperStatusFlags
heißen
wobei InterfaceAndOperStatusFlags dann eine Struktur wäre:

Code: Alles auswählen

Structure InterfaceAndOperStatusFlags
  HardwareInterface.b
  FilterInterface.b
  ConnectorPresent.b
  NotAuthenticated.b
  NotMediaConnected.b
  Paused.b
  LowPower.b
  EndPointInterface.b
EndStructure

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 15:01
von GPI
das original sieht so aus:

Code: Alles auswählen

struct {
    BOOLEAN HardwareInterface  :1;
    BOOLEAN FilterInterface  :1;
    BOOLEAN ConnectorPresent   :1;
    BOOLEAN NotAuthenticated  :1;
    BOOLEAN NotMediaConnected  :1;
    BOOLEAN Paused  :1;
    BOOLEAN LowPower  :1;
    BOOLEAN EndPointInterface  :1;
  } InterfaceAndOperStatusFlags;
:1 beudeutet hier Ein Bit von Typ Boolean. GEsamt also eigent 8 BIt=1Byte

damit wären es aber eigentlich 7Bytes, wo meine Structur zu klein ist :)

Kurzer Test ergab auch, das die Werte dann in den Bereich nicht sinnvoll sind.

Erklärt zudem nicht die allgemeine 4 Byte-Verschiebung

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 16:06
von Kiffi
<OT>

Welcome back, GPI! :D

</OT>

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 17:56
von DarkDragon
http://msdn.microsoft.com/en-us/library ... 85%29.aspx

NET_LUID hat 2 quads:

Code: Alles auswählen

InterfaceLuid.b[16] ; Zwei Quads
Ach ne ist ja ne union.. sowas gibts ja auch global, sorry.

[EDIT] (hoffentlich hat ers nicht schon davor gelesen und liest es jetzt nichtmehr)

InterfaceIndex.q muss es heißen.

Ich hab in C einfach mal ein Testprogramm erstellt, welches das hier als semantischen Inhalt hatte:

printf("%d", sizeof(MIB_IF_ROW2));

Und dann habe ich Teile der Struktur parallel in PB und C auskommentiert bis ich den Fehler hatte.

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 19:38
von GPI
index-als quad kann nicht sein. dann würde ein Index von 51539673088 bspw. rauskommen. das ist falsch...

aber kannst du bitte was anderes machen? Von der C-Structur ein Offset zu jeden punkt in der Liste?

Also:
+0 InterfaceLuid.q ; Ein Quad
+8 InterfaceIndex.l
+12 InterfaceGuid.b[4+2+2+8]

etc?

Dann könnte ich rausbekommen wo der fehler liegt.

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 19:46
von DarkDragon
GPI hat geschrieben:index-als quad kann nicht sein. dann würde ein Index von 51539673088 bspw. rauskommen. das ist falsch...

aber kannst du bitte was anderes machen? Von der C-Structur ein Offset zu jeden punkt in der Liste?

Also:
+0 InterfaceLuid.q ; Ein Quad
+8 InterfaceIndex.l
+12 InterfaceGuid.b[4+2+2+8]

etc?

Dann könnte ich rausbekommen wo der fehler liegt.

Code: Alles auswählen

0
8
12
542
1056
1056
1092
1124
1124
1128
1132
1136
1140
1144
1148
1152
1156
1160
1164
1168
1184
1192
1200
1208
1216
1224
1232
1240
1248
1256
1264
1272
1280
1288
1296
1304
1312
1320
1328
1336
1344
Generiert mit diesem Code in der main:

Code: Alles auswählen

printf("%d\n", offsetof(MIB_IF_ROW2, InterfaceLuid));
printf("%d\n", offsetof(MIB_IF_ROW2, InterfaceIndex)); 

    //
    // Read-Only fields.
    //
printf("%d\n", offsetof(MIB_IF_ROW2, InterfaceGuid));
printf("%d\n", offsetof(MIB_IF_ROW2, Alias[IF_MAX_STRING_SIZE + 1])); 
printf("%d\n", offsetof(MIB_IF_ROW2, Description[IF_MAX_STRING_SIZE + 1]));
printf("%d\n", offsetof(MIB_IF_ROW2, PhysicalAddressLength));
printf("%d\n", offsetof(MIB_IF_ROW2, PhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH]));
printf("%d\n", offsetof(MIB_IF_ROW2, PermanentPhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH]));    

printf("%d\n", offsetof(MIB_IF_ROW2, Mtu));
printf("%d\n", offsetof(MIB_IF_ROW2, Type));                // Interface Type.
printf("%d\n", offsetof(MIB_IF_ROW2, TunnelType));     // Tunnel Type, if Type = IF_TUNNEL.
printf("%d\n", offsetof(MIB_IF_ROW2, MediaType)); 
printf("%d\n", offsetof(MIB_IF_ROW2, PhysicalMediumType)); 
printf("%d\n", offsetof(MIB_IF_ROW2, AccessType));
printf("%d\n", offsetof(MIB_IF_ROW2, DirectionType));
printf("%d\n", offsetof(MIB_IF_ROW2, InterfaceAndOperStatusFlags));
    
printf("%d\n", offsetof(MIB_IF_ROW2, OperStatus));  
printf("%d\n", offsetof(MIB_IF_ROW2, AdminStatus));
printf("%d\n", offsetof(MIB_IF_ROW2, MediaConnectState));
printf("%d\n", offsetof(MIB_IF_ROW2, NetworkGuid));
printf("%d\n", offsetof(MIB_IF_ROW2, ConnectionType)); 

    //
    // Statistics.
    //
printf("%d\n", offsetof(MIB_IF_ROW2, TransmitLinkSpeed));
printf("%d\n", offsetof(MIB_IF_ROW2, ReceiveLinkSpeed));

printf("%d\n", offsetof(MIB_IF_ROW2, InOctets));
printf("%d\n", offsetof(MIB_IF_ROW2, InUcastPkts));
printf("%d\n", offsetof(MIB_IF_ROW2, InNUcastPkts));
printf("%d\n", offsetof(MIB_IF_ROW2, InDiscards));
printf("%d\n", offsetof(MIB_IF_ROW2, InErrors));
printf("%d\n", offsetof(MIB_IF_ROW2, InUnknownProtos));
printf("%d\n", offsetof(MIB_IF_ROW2, InUcastOctets));      
printf("%d\n", offsetof(MIB_IF_ROW2, InMulticastOctets));  
printf("%d\n", offsetof(MIB_IF_ROW2, InBroadcastOctets)); 
printf("%d\n", offsetof(MIB_IF_ROW2, OutOctets));
printf("%d\n", offsetof(MIB_IF_ROW2, OutUcastPkts));
printf("%d\n", offsetof(MIB_IF_ROW2, OutNUcastPkts));
printf("%d\n", offsetof(MIB_IF_ROW2, OutDiscards));
printf("%d\n", offsetof(MIB_IF_ROW2, OutErrors));
printf("%d\n", offsetof(MIB_IF_ROW2, OutUcastOctets));     
printf("%d\n", offsetof(MIB_IF_ROW2, OutMulticastOctets)); 
printf("%d\n", offsetof(MIB_IF_ROW2, OutBroadcastOctets));   
printf("%d\n", offsetof(MIB_IF_ROW2, OutQLen));
Komischerweise kommt bei offsetof etwas widersprüchliches raus. Jedoch, wenn ich sizeof mit dem ersten Strukturelement mache komme ich auf 8, mit dem zweiten auf 16. Ich kanns noch so oft wiederholen :? .

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 22:49
von GPI
Danke, kleinen Fehler hast du in Programm.

Code: Alles auswählen

PhysicalAddress[IF_MAX_PHYS_ADDRESS_LENGTH]));
damit bestimmst du die position eins nach den ende des feldes. Korrekt wäre hier:

Code: Alles auswählen

PhysicalAddress[0]));
Aber ich hab den Fehler in der Struktur gefunden - und ohne dich vermutlich nie.

ConnectionType ist ein Quad! - darauf muss man auch erstmal kommen...

Und anscheinend startet die Daten tatsächlich bei +8 (die Anzahl der Interfaces wird wohl auch in Quad übergeben - keine ahnung warum da die über 1 Mio nicht ausreicht, das mit 32-bit möglich wäre :) )

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 23:24
von freak
GPI hat geschrieben:ConnectionType ist ein Quad! - darauf muss man auch erstmal kommen...

Und anscheinend startet die Daten tatsächlich bei +8 (die Anzahl der Interfaces wird wohl auch in Quad übergeben - keine ahnung warum da die über 1 Mio nicht ausreicht, das mit 32-bit möglich wäre :) )
Das sind keine Quad, sondern Long mit 4 byte padding (4 ungenutzte Byte) dahinter. Die existieren damit die danach kommenden größeren Werte (wie zum Beispiel ULONG64) korrektes Alignment haben.

Daraus muss man ein Long machen und dann einen Dummy-Feld einfügen. Wenn du ein Quad draus machst ließt du eventuell ungenützte Bytes mit in den Wert ein (und die müssen ja nicht immer 0 sein).

Re: GetIfTable2 - wie funktionierts richtig?

Verfasst: 11.09.2010 23:26
von GPI
Woran erkennt man sowas? Sieht für mich mehr oder minder so aus, als werden die willkürlich eingefügt. Oder werden Quads in C immer an durch 4 Teilbare adressen erzeugt?