Autor Beitrag
thomaskroger
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mi 07.03.12 18:20 
Tach auch,

Inet_Addr meldet bei Delphi 7 beim Ergebnistyp cardinal eine Bereichsüberschreitung wenn die IP größer als xxx.xxx.xxx.127 ist.

Sehe ich das richtig ?

Folgendes Beispiel:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
  
var
  s,s1,s2   : string;
  c1  : int64;
  c2  :cardinal;
begin
  s:=Edit1.Text;
  c1 := Inet_Addr(PChar(s));
  c2 := Inet_Addr(PChar(s));
  s1 := IntToHex(c1, 10);
  s2 := IntToHex(c2, 8);
...
end;



Im o.g. Beispiel ergibt die IP s:='192.168.1.2' die Hex-Ausgabe c1:=0201A8C0 also 02.01.A8.C0 in Dezimal 2.1.168.192
Die IP-Adresse 192.168.1.2 beginnt also mit dem Low-Byte! In vielen Postings im Forum wird es übrigens (mit cardinal) anderherum umgerechnet.

Das hat zur Konsequenz, dass ein cardinal-Typ bei 192.168.2.127 mit dem Ergebnis 7F01A8C0 korrekt arbeitet, aber bei 192.168.2.128 (=8001A8C0) einen Bereichsfehler ergibt da Inet_Addr ein negatives Ergebnis zurückgibt. Was in cardinal nicht definiert ist.
Der Typ int64 (in c1) gibt bei 192.168.2.128 den Wert (..FF)8001A8C0.

Also ist hier ein typecast mit
ausblenden Delphi-Quelltext
1:
2:
 
c2 := cardinal(Inet_Addr(PChar(s)));

angesagt.

Eine Subtraktion von 192.168.2.128 - 192.168.2.127 ergibt somit Hex 1000000 was nach Wandlung in IP (inet_ntoa) wiederum dez 1 gibt.

Dann ist die IP im IP-Header als 32-Bit Adresse mit führendem Low-Bit? Im Wireshark ist sie jedenfalls mit führendem Lo-Byte zu sehen. Also sozusagen mit der 192. beginnend.

Oder ist da etwas falsch?
Martok
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 3661
Erhaltene Danke: 604

Win 8.1, Win 10 x64
Pascal: Lazarus Snapshot, Delphi 7,2007; PHP, JS: WebStorm
BeitragVerfasst: Mi 07.03.12 20:07 
Ah, die Freuden der Network Byte Order.

Wie so oft steht die Antwort im Handbuch:
Zitat:
All Internet addresses are returned in IP's network order (bytes ordered from left to right).

C1 enthält also den korrekten Wert in Network Order. Beispiel:
'1.2.3.4' -> 67305985 -> Hex($04030201). Im Speicher liegt das als $01 $02 $03 $04, also richtigrum.
Wenn du sie für irgendwas (mir fällt nichts ein; alle Netzwerkfunktionen arbeiten in Network Order) andersrum brauchst, gibts ntohl und wieder zurück mit htonl.

Der Rest deines Beitrags erklärt dann das Zweierkomplement.

Was war jetzt die Frage? Achja, die Bereichsüberprüfung.
Das geht auf einen Fehler in der Header-Übersetzung von Borland zurück. inet_ntoa gibt u_long zurück, was als Longint definiert ist. Es müsste eigentlich ein Cardinal sein. Generell sind alle 32bit-unsigned-Typen als signed abgebildet - immerhin also konsequent falsch.
Statt Cardinal u_long verwenden sollte also helfen.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
  {$R+}
var c: u_long;
begin
  c:= inet_addr('129.129.129.129');  // funktioniert

_________________
"The phoenix's price isn't inevitable. It's not part of some deep balance built into the universe. It's just the parts of the game where you haven't figured out yet how to cheat."

Für diesen Beitrag haben gedankt: thomaskroger
thomaskroger Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Do 08.03.12 14:58 
Hallo Martok,
danke für die ausführliche Antwort.

Ja, wir finden alles in Handbüchern, nur können wir die nicht alle lesen... Glücklicherweise gibt es Foren wo die Wissenen ihr Wissen mit Unwissenden teilen. Und anders als beim Käse wird das Wissen dadurch nicht kleiner :)

Nun gut...

"dwRemoteIP:u_long" funktioniert mit "dwRemoteIP:=inet_addr(PChar(address)))" nur das folgende "SendARP(dwremoteIP,..." jammert dann über den falschen Typ.

das nimmt er:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
var
  res,dwRemoteIP: cardinal;
  PhyAddrLen: Longword;
  pMacAddr : array [0..1of Longword;
  address: String;

begin
  dwRemoteIP := cardinal(inet_addr(PChar(address)));
  ...
  res:=SendARP(dwremoteIP, 0, @pMacAddr, @PhyAddrLen);