2017-10-31 5 views
1

C++のRAWソケットを使用して、すべてのICMP "宛先到達不能 - ポート到達不能"メッセージをキャッチしようとしています。次に、基礎となるUDPプロトコルを処理して、宛先に到達できなかったポートを検出します。これまでのところ、私はICMPメッセージを受信し、そのタイプとコードに基づいてフィルタリングしました。しかし、私はudpヘッダーにアクセスするのに苦労しています。ICMPメッセージからUDPにアクセスする

*(struct udphdr*)(icmp + sizeof(struct icmphdr) + sizeof(struct iphdr)) 

struct iphdr *ip = (struct iphdr*)ether_frame; 
struct icmphdr *icmp = (struct icmphdr*)(ether_frame + ip->ihl*4); 
struct iphdr *ip2 = (struct iphdr*)(icmp + sizeof(struct icmphdr)) 
struct udphdr *udphdr = (struct udphdr*)(ip2 + ip2->ihl*4) 

しかし、どちらもが働いていた:これまでのところ私はこれらを試してみました。私はそれが単純なポインタの算術ミスであると確信していますが、私はそれを理解することはできません。だから私の質問は次のとおりです。プロトコルはどのくらい正確にICMPレスポンスで編成されていますか?未処理のicmp応答から到達できなかったポート番号にどのようにアクセスできますか?

EDIT:this->rcv_sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMPを使用して作成された応答がether_frameサイズIP_MAXPACKETuint8_t配列でrecv(this->rcv_sd, ether_frame, IP_MAXPACKET, 0)を使用して受信される受信するために使用されるソケット。

+1

"*プロトコルはどのくらい正確にICMPレスポンスで整理されていますか?" - Wiresharkなどのパケットスニファ+アナライザを使用して実際のパケット構造を確認することをお勧めします。 –

+0

もちろん、私はそれをしましたが、私の最初のtry( 'struct udphdr *)(icmp + sizeof(struct icmphdr)+ sizeof(struct iphdr)')は、 wireshark。 – sveatlo

+0

はい、それ以外の場合は、icmpのタイプとコードに基づいてフィルタリングできませんでした。私もgdbでそれらを見て、内容は(予想どおり)wiresharkで見た内容と同じでした。 – sveatlo

答えて

3

(icmp + sizeof(struct icmphdr))(ip2 + ip2->ihl*4)のようなステートメントは、あなたが間違ったアドレスに終わる原因となっているように、structポインタにバイトカウントを追加するので、pointer arithmeticを使用しています。

型付きポインタに数値を追加すると、ポインタは、基になる型のバイト数に指定した数値を掛けて調整されます。

ので、この:

struct iphdr *ip2 = (struct iphdr*)(icmp + sizeof(struct icmphdr)) 

がこれに相当します

struct iphdr *ip2 = (struct iphdr*)(((uint8_t*)icmp) + (sizeof(*icmp) * sizeof(struct icmphdr))) 

そして、この:

struct udphdr *udphdr = (struct udphdr*)(ip2 + ip2->ihl*4) 

がこれに相当します

struct udphdr *udphdr = (struct udphdr*)(((uint8_t*)ip2) + (sizeof(*ip2) * (ip2->ihl*4))) 

あなたがバイトではなく、要素によって、あなたの構造体へのポインタをオフセットしたいので、あなたが入力し、キャストするバイトのポインタへの構造体のポインタをそれらにバイトカウントを追加する前に、必要があります。

struct iphdr *ip2 = (struct iphdr*)(((uint8_t*)icmp) + sizeof(struct icmphdr)) 
// or simpler, using correct pointer arithmetic: 
// struct iphdr *ip2 = (struct iphdr*)(icmp + 1) 

struct udphdr *udphdr = (struct udphdr*)(((uint8_t*)ip2) + (ip2->ihl*4)) 

あなたがこの問題を持っていませんether_frameがポインタのように崩壊するuint8_tの配列であるため、ipicmpポインタをether_frameバッファから割り当てます。

関連する問題