Auf ICMP-Pakete in C # warten

7

Ich habe eine SIP-Anwendung, die UDP-Pakete senden muss, um die SIP-Anrufe einzurichten. SIP verfügt über einen Timeout-Mechanismus, um Zustellungsfehler zu beheben. Eine weitere Sache, die ich gerne tun könnte, ist festzustellen, ob ein UDP-Socket geschlossen ist, um das 32s-Retransmit-Intervall warten zu müssen, das SIP verwendet.

Die Fälle, auf die ich mich beziehe, sind, wenn ein Versuch, an einen UDP-Socket zu senden, dazu führt, dass ein ICMP Destination Unreachable-Paket vom entfernten Host erzeugt wird. Wenn ich versuche, ein UDP-Paket an einen Host zu senden, der oben ist, aber der Port nicht zuhört, kann ich die ICMP-Nachricht mit einem Paketracer zurückkommen sehen, aber die Frage ist, wie bekomme ich Zugriff darauf von meinem C # -Code? p>

Ich spiele gerade mit rohen Sockets herum, konnte aber bisher nicht die ICMP-Pakete von meinem Programm empfangen. Das folgende Beispiel empfängt niemals ein Paket, obwohl ICMP-Nachrichten auf meinem PC ankommen.

%Vor%

Im Folgenden finden Sie eine Kabelverfolgung, die die ICMP-Antworten zeigt, die von einem Versuch, ein UDP-Paket von 10.0.0.100 (mein PC) an 10.0.0.138 (mein Router) an einem Port zu senden, auf den ich höre. Mein Problem ist, wie man diese ICMP-Pakete verwendet, um zu realisieren, dass das UDP-Senden fehlgeschlagen ist, anstatt nur auf die Zeitüberschreitung der Anwendung nach einer willkürlichen Periode zu warten?

    
sipwiz 09.03.2009, 14:51
quelle

7 Antworten

13

Fast 3 Jahre später bin ich über Ссылка gestolpert, was mir genug gegeben hat eines Hinweises, der mir helfen soll, eine Lösung für den Empfang von ICMP-Paketen unter Windows 7 zu finden (weiß nicht über Vista, worum es bei der ursprünglichen Frage ging, aber ich vermute, dass diese Lösung funktionieren würde).

Die zwei Schlüsselpunkte sind, dass der Socket an eine einzelne spezifische IP-Adresse gebunden sein muss, und nicht an IPAddress.Any und den IOControl-Aufruf, der das SIO_RCVALL-Flag setzt.

%Vor%

Ich musste auch eine Firewall-Regel festlegen, um ICMP Port Unreachable Pakete empfangen zu können.

%Vor%     
sipwiz 07.02.2012, 10:13
quelle
3

Icmp verwendet einen Bezeichner , der für jede icmp "Sitzung" unterschiedlich zu sein scheint (für jeden icmp Socket). Daher wird die Antwort auf ein ICMP-Paket, das nicht vom selben Socket gesendet wird hilfreicherweise für Sie herausgefiltert . Aus diesem Grund wird dieses Stück Code nicht funktionieren. (Ich bin mir nicht sicher. Es ist nur eine Annahme, nachdem ich ICMP-Traffic angeschaut habe.)

Sie könnten einfach den Host anpingen und sehen, ob Sie ihn erreichen können oder nicht und dann versuchen Sie Ihr SIP-Ding. Dies funktioniert jedoch nicht, wenn der andere Host ICMP ausfiltert.

Eine hässliche (aber funktionierende) Lösung verwendet winpcap . (Dies als einzige funktionierende Lösung zu haben, scheint einfach zu schlecht zu sein, um wahr zu sein.)

Was ich mit winpcap meine, ist, dass Sie ICMP-Verkehr erfassen und dann sehen können, ob das erfasste Paket davon handelt, dass Ihr UDP-Paket nicht zustellbar ist .

Hier ist ein Beispiel für die Erfassung von TCP-Paketen: Ссылка (Es sollte nicht zu schwer sein, das gleiche mit ICMP zu tun.)

    
Tarnay Kálmán 15.03.2009 07:20
quelle
3

UPDATE: Ich denke, ich werde verrückt ... Dieser Code, den du gepostet hast, funktioniert auch für mich ...

Das folgende Stück Code funktioniert für mich (xp sp3):

%Vor%     
Tarnay Kálmán 20.03.2009 02:00
quelle
3

Verwenden Sie einfach angeschlossene Udp-Sockets und das Betriebssystem wird dem icmp nicht erreichbar und gibt einen Fehler im Udp-Socket zurück.

Google für verbundene udp-Sockets.

    
haesbaert 08.08.2011 15:40
quelle
2

Es gibt eine Reihe von Posts im Internet, in denen das Problem von ICMP Port Unreachable-Paketen erwähnt wird, auf die unter Vista nicht mehr zugegriffen werden kann.

Der Stapel sollte Ihnen eine Ausnahme zurückgeben, wenn er den ICMP empfängt. Aber es ist nicht, zumindest auf Vista. Und deshalb versuchen Sie eine Abhilfe.

Ich mag keine Antworten, die sagen, dass es nicht möglich ist, aber es scheint so. Also schlage ich vor, du gehst einen Schritt zurück zum ursprünglichen Problem, das lange Timeouts im SIP waren.

  • Sie können den Benutzer konfigurieren lassen Timeout (also Art der Einhaltung von die Spezifikation).
  • Sie können vorher andere Dinge tun (wie zum Beispiel andere Proxies überprüfen) Die Zeitüberschreitung endet.
  • Sie konnten bekannte ungültige Ziele zwischenspeichern (aber das würde brauchen gute Verwaltung des Caches.
  • Wenn icmp und udp keine korrekten Fehlermeldungen ausgeben, versuchen Sie tcp oder ein anderes Protokoll. Nur um die gewünschten Informationen zu erhalten.

(Alles ist möglich, es kann eine Menge Ressourcen erfordern.)

    
Conor OG 20.03.2009 09:25
quelle
1

Ich schreibe dies als eine separate Antwort, da die Details völlig anders sind als die, die ich zuvor geschrieben habe.

Auf der Grundlage des Kommentars von Kalmi über die Sitzungs-ID habe ich mich daher Gedanken darüber gemacht, warum ich zwei Ping-Programme auf demselben Rechner öffnen kann und die Antworten nicht kreuzen. Sie sind beide ICMP und verwenden daher portlose rohe Sockets. Das bedeutet etwas im IP-Stack, muss wissen, für welchen Socket diese Antworten bestimmt waren. Für Ping stellt sich heraus, dass eine ID in den Daten des ICMP-Pakets als Teil von ECHO REQUEST und ECHO REPLY verwendet wird.

Dann habe ich diesen Kommentar auf Wikipedia über ICMP durchgelesen:

  

Obwohl ICMP-Nachrichten enthalten sind   in Standard-IP-Datagrammen, ICMP   Nachrichten werden normalerweise als a verarbeitet   Sonderfall, unterschieden von   normale IP-Verarbeitung, anstatt   als normales Subprotokoll von   IP. In vielen Fällen ist es notwendig,   Überprüfen Sie den Inhalt des ICMP   Nachricht und liefern das Passende   Fehlermeldung an die Anwendung, die   erzeugt das ursprüngliche IP-Paket, das   eine, die das Senden der   ICMP-Nachricht.

Was (indirekt) hier ausgearbeitet wurde:

  

Der Internet-Header plus die ersten 64   Bits der Daten des ursprünglichen Datagramms.   Diese Daten werden vom Host für die Übereinstimmung verwendet   die Nachricht an die entsprechende   verarbeiten. Wenn ein höheres Protokoll   verwendet Portnummern, von denen angenommen wird   in den ersten 64 Datenbits der   Originaldatagram Daten.

Da Sie UDP verwenden, das Ports verwendet, ist es möglich, dass der Netzwerkstapel die ICMP-Nachricht an den ursprünglichen Socket zurückleitet. Dies ist der Grund, warum Ihr neuer und separater Socket diese Nachrichten niemals empfängt. Ich stelle mir vor, UDP isst die ICMP-Nachricht.

Wenn ich richtig liege, ist eine Lösung dafür, einen unformatierten Socket zu öffnen und manuell Ihre UDP-Pakete zu erstellen, auf das Zurückkommende zu warten und UDP- und ICMP-Nachrichten entsprechend zu behandeln. Ich bin mir nicht sicher, wie das im Code aussehen würde, aber ich kann mir nicht vorstellen, dass es zu schwierig wäre, und könnte als "eleganter" angesehen werden als die winpcap-Lösung.

Zusätzlich scheint dieser Link, Ссылка , eine großartige Ressource für Netzwerkprotokolle niedriger Ebene zu sein.

>

Ich hoffe, das hilft.

    
grieve 18.03.2009 16:53
quelle
1

Sie möchten also das Programm dest unreachable return icmp programmgesteuert aufnehmen? Eine schwierige Frage. Ich würde sagen, der Netzwerk-Stack saugt das auf, bevor man in die Nähe kommen kann.

Ich glaube nicht, dass ein reiner C # -Ansatz hier funktioniert. Sie müssen einen Treiber-Level-Intercept verwenden, um einen Haken zu bekommen. Sehen Sie sich diese App an, die windows 'ipfiltdrv.sys verwendet, um Pakete (icmp, tcp, udp usw.) zu fangen und sie mit verwaltetem Code zu lesen / spielen ( c #).

Ссылка

  • Oisin
x0n 18.03.2009 17:14
quelle

Tags und Links