2016-06-22 7 views
2

sendmsg経由で未処理のイーサネットパケットを送信するためにCを使用しようとしています。このコードは、生のパケットソケットを正常にオープンし、構造体のiovecに1バイトの配列(char message [])を入力しようとし、次に構造体msghdrに宛先アドレス、アドレスの長さ、および構造体iovecメッセージ。 sendmsg()はすべての呼び出しに対してEINVALを返しますが、無効な引数は何もわかりません。 (このコードを読みやすくするためにいくつかのperror()呼び出しを削除しました。出力は "無効な引数"です)生のイーサネットフレームでsendmsg/sendmmsgを使用する

sendmsg()がrawとどのように機能するかの例は見つかりませんでしたsendto()を使って同様のコードを期待どおりに動作させます。そのコードでは、私はヘッダーとプロトコル情報を含むイーサネットフレームを明示的に形成しますが、sendmsg()呼び出しでは必要ではないことを理解していますか?私はまた、message.iov_baseが14バイトのヘッダを含む明示的に形成されたイーサネットフレームを含むバッファを指し示すように試みましたが、sendmsg()もそれを嫌にします。

生のイーサネットフレームでsendmsg()とsendmmsg()を動作させることはできますか?それを無効にしているiovecについて、私が見逃していることはありますか?

30 int main(void) { 
32   unsigned char dest[ETH_ALEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11}; // destination MAC address 
33 
34   // Socket variables 
35   int    s; 
36   unsigned short protocol = htons(ETH_P_802_EX1); 
38 
39   // Message variables 
40   char   message[] = {"Test message. Test message. Test message!\n"}; 
41   size_t   msg_len = strlen(message) + 1;   // Message length includes null terminator 
42   int    e;          // Error code 
43   struct msghdr msg; 
44   struct iovec msgvec; 
45 
46   // Setup source-side socket 
47   s = socket(AF_PACKET, SOCK_RAW, protocol); 
48   if (s < 0) { printf("%d: %s\n", errno, strerror(errno)); return EXIT_FAILURE; } 
49 
50   msgvec.iov_base = message; 
51   msgvec.iov_len = msg_len; 
52   memset(&msg, 0, sizeof(msg)); 
53   msg.msg_name = dest; 
54   msg.msg_namelen = ETH_ALEN; 
55   msg.msg_control = NULL; 
56   msg.msg_controllen = 0; 
57   msg.msg_flags = 0; 
65   msg.msg_iov = &msgvec; 
66   msg.msg_iovlen = 1; 
67 
68   for (int i=0; i<10; i++) { 
69     e = sendmsg(s, &msg, 0); 
73   } 
79   close(s); 
80   return EXIT_SUCCESS; 
81 } 

答えて

3

私はこのコードをいくつかの調整を行った後に動作させました。

sendmsg()のマニュアルページで暗示されているように、アドレスをバイト列として送信する代わりに、struct sockaddr_llを使用しました。私はまた、ヘッダーを含む完全なイーサネットフレームを含むバッファーにiovecを指摘しました。なぜmanページがsendtoプロトタイプのconst構造体sockaddr *を明示的に指定するのですが、msghdr定義のvoid *はわかりません。

I)は、(ソケットを呼び出した後、このコードを追加:

39   struct sockaddr_ll address; 
40   struct ifreq buffer;         // To get information with ioctl() 
41   char   ifname[] = {"eth0"}; 
42   int    ifindex;        // Interface index, from ioctl() call 

57   memset(&buffer, 0, sizeof(buffer));      // Getting interface index value 
58   strncpy(buffer.ifr_name, ifname, IFNAMSIZ); 
59   ioctl(s, SIOCGIFINDEX, &buffer); 
60   ifindex = buffer.ifr_ifindex; 
61 
62   // Setup sockaddr_ll address 
63   memset((void*) &address, 0, sizeof(address)); 
64   address.sll_family = PF_PACKET; 
65   address.sll_ifindex = ifindex; 
66   address.sll_halen = ETH_ALEN; 
67   memcpy((void*) (address.sll_addr), (void*) dest, ETH_ALEN); 

とのmsghdr構造体の割り当てのためのコードのこれらの行置換:

81   msg.msg_name = &address; 
82   msg.msg_namelen = sizeof(address); 
関連する問題