2

Linux 上の C で Libpcap を使用して小さなアプリケーションを作成したいと考えています。

現在、パケットのスニッフィングと待機を開始しています。しかし、それは私が実際に必要としているものではありません。N 秒待ってからリッスンを停止します。

どうすればそれを達成できますか?

これが私のコードです:

void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
{
       printf("got packet\n);
}

int main()
{
 int ret = 0;
 char *dev = NULL;   /* capture device name */
 char errbuf[PCAP_ERRBUF_SIZE];  /* error buffer */
 pcap_t *handle;    /* packet capture handle */

 char filter_exp[] = "udp dst port 1500";  /* filter expression */
 struct bpf_program fp;   /* compiled filter program (expression) */
 bpf_u_int32 mask;   /* subnet mask */
 bpf_u_int32 net;   /* ip */
 int num_packets = 10;   /* number of packets to capture */


 /* get network number and mask associated with capture device */
 if (pcap_lookupnet(dev, &net, &mask, errbuf) == -1) {
  fprintf(stderr, "Couldn't get netmask for device %s: %s\n",
      dev, errbuf);
  net = 0;
  mask = 0;
 }


 /* print capture info */
 printf("Device: %s\n", dev);
 printf("Number of packets: %d\n", num_packets);
 printf("Filter expression: %s\n", filter_exp);




 /* open capture device */
 handle = pcap_open_live(dev, SNAP_LEN, 1, 1000, errbuf);
 if (handle == NULL) {
  fprintf(stderr, "Couldn't open device %s: %s\n", dev, errbuf);
  exit(EXIT_FAILURE);
 }



 /* compile the filter expression */
 if (pcap_compile(handle, &fp, filter_exp, 0, net) == -1) {
  fprintf(stderr, "Couldn't parse filter %s: %s\n",
      filter_exp, pcap_geterr(handle));
  exit(EXIT_FAILURE);
 }

 /* apply the compiled filter */
 if (pcap_setfilter(handle, &fp) == -1) {
  fprintf(stderr, "Couldn't install filter %s: %s\n",
      filter_exp, pcap_geterr(handle));
  exit(EXIT_FAILURE);
 }

 /* now we can set our callback function */
 pcap_loop(handle, num_packets, got_packet, NULL);

 /* cleanup */
 pcap_freecode(&fp);
 pcap_close(handle);
}
4

4 に答える 4

7

pcap_breakloop()聞くのをやめたいときは電話するべきです。したがって、1つの方法は次のとおりです。

  • N秒でトリガーするようにアラームを設定し、
  • シグナルのシグナルハンドラをインストールしSIGALRM
  • pcap_breakloop()ハンドラー内で呼び出してpcap_loop()戻ります。

コード:

void alarm_handler(int sig)
{
    pcap_breakloop(handle);
}

int main()
{
    ...

    alarm(N);
    signal(SIGALRM, alarm_handler);

    /* now we can set our callback function */
    pcap_loop(handle, num_packets, got_packet, NULL);

    /* cleanup */
    pcap_freecode(&fp);
    pcap_close(handle);
}

注: これを行うために libpcap の読み取りタイムアウトを使用することに関しては、それは機能せず、機能しません。man pcap は明示的にそれに対して警告します:

読み取りタイムアウトを使用して、パケットを読み取る呼び出しが限られた時間内に返されるようにすることはできません [...] これは、読み取りタイムアウトを使用しないことを意味します。ユーザー入力を定期的にポーリングします。これは、パケットが到着していない場合でも、タイムアウトの期限が切れた後にパケットを読み取る呼び出しが返されるという保証がないためです。

于 2012-12-06T17:51:43.873 に答える
2

tcpdump Web サイトからこのページを見ると、次のことがわかります。

スニッフィングのためにデバイスを開く

スニッフィング セッションを作成するタスクは非常に簡単です。このために、pcap_open_live() を使用します。この関数のプロトタイプ (pcap man ページから) は次のとおりです。

pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms,
                       char *ebuf)

最初の引数は、前のセクションで指定したデバイスです。snaplen は、pcap によってキャプチャされる最大バイト数を定義する整数です。promisc を true に設定すると、インターフェイスが無差別モードになります (ただし、false に設定されている場合でも、特定のケースではインターフェイスが無差別モードになる可能性があります)。to_ms はミリ秒単位の読み取りタイムアウトです (値 0 はタイムアウトがないことを意味します。少なくとも一部のプラットフォームでは、十分な数のパケットが到着するまで待機してからパケットを確認できることを意味します。したがって、ゼロ以外の値を使用する必要があります。タイムアウト) . 最後に、ebuf はエラー メッセージを格納できる文字列です (上記の errbuf で行ったように)。この関数は、セッション ハンドラを返します。

これが機能しない場合は、お知らせください。

于 2011-01-03T10:21:22.133 に答える
0

私はしばらくの間、これらのコード フラグメントを研究し、テストしてきました。どこかで、pcap_loop を終了すると、パケットが表示された可能性がありますが、終了条件は何も表示されていないことを示していることに気付きました。このことから、パケットのすべての処理はコールバック関数のスコープ内で発生する必要があると想定しています。したがって、すぐにリセットして別のパケットの準備をしたい場合は、別のプロセスを生成して各パケットを処理する必要があります。

于 2016-05-10T21:19:23.697 に答える