2

socket() を呼び出すときに、PF_PACKET と SOCK_RAW およびカスタム プロトコルを使用して、サーバー/クライアント ソフトウェアを構築しています。

クライアントソフトウェアで同じ方法でソケットを作成し、そのソケットからrcvを実行するだけでデータを取得できます

私の質問は、クライアントから返信するときに取得した送信元MACアドレスが11:11:00:00:00:00のような奇妙なものであるため、サーバーと同じ方法でsockaddr_ll構造体に入力する必要があるかどうかです。もちろん、これは私のクライアントのMACではありません

これが何が起こるか知っている人はいますか?ソケットを開く

if ( (sckfd=socket(PF_PACKET, SOCK_RAW, htons(proto)))<0)
{
    myError("socket");

}

これが私がデータを受け取る方法です

n = recvfrom(sckfd, buffer, 2048, 0, NULL, NULL);
printf("%d bytes read\n",n);

したがって、これは基本的に、構造体 sockaddr_ll を埋めずにクライアントでデータを受信する方法です

サーバープログラムの場合、構造体を埋める必要があります

struct sockaddr_ll saddrll;
memset((void*)&saddrll, 0, sizeof(saddrll));
saddrll.sll_family = PF_PACKET;   
saddrll.sll_ifindex = ifindex;
saddrll.sll_halen = ETH_ALEN;
memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);

私の質問は、示されているように受信し、示されているように送信し、サーバーに返信するときに、送信のためにサーバーで使用されているのと同じ関数を呼び出すと、クライアントの返信を受信するときに 11:11:00:00:00:00 を取得することです

4

1 に答える 1

2

おそらく使用する必要があります

socket(AF_PACKET, SOCK_DGRAM, htons(proto)))

SOCK_RAW ソケットの代わりに。SOCK_RAW を使用すると、送信元と宛先の MAC アドレスを含むイーサネット フレーム全体を送受信します。SOCK_DGRAM を使用すると、カーネルがイーサネット ヘッダーを埋めます。

おそらく、リクエストが送信されたのと同じアドレスに返信を送信したいでしょう。recvfrom() は送信元アドレスを埋めることができます。

struct sockaddr_ll src_addr;
socklen_t addr_len = sizeof src_addr;
n = recvfrom(sckfd, buffer, 2048, 0, 
            (struct sockaddr*)&src_addr, &addr_len);

送信元アドレスがわかったので、そこにパケットを送り返します。

...
sendto(sckfd, data, data_len, src_addr, addr_len);

また、SOCK_RAW を使用する必要がある場合は、イーサネット ヘッダーも受信するので、受信したデータから MAC アドレスをコピーして、応答フレームを作成するときにそれらを交換します。

SOCK_RAW ソケットの場合、イーサネット フレーム全体を作成します。イーサネット アドレスを入力する必要がないため、次の手順は不要です。

 memcpy((void*)(saddrll.sll_addr), (void*)dest, ETH_ALEN);
于 2013-11-06T23:05:23.290 に答える