• ベストアンサー

IPアドレスを配列に代入する方法。

パケットモニタリング(tcpdumpみたいなもの)でIPアドレスを取得するプログラムがあるのですが、IPアドレスを配列に代入することが出来ません。 パケットモニタリングのソース void print_ip(struct ip *ip) { printf("| Source IP Address: %15s|\n", inet_ntoa(*(struct in_addr *) &(ip->ip_src))); /* ループ */ 実行画面 | Source IP Address: 12.34.56.78 | | Source IP Address: 34.56.78.09 | ・ ・ というふうにどんどん取得、表示していく このIPアドレス inet_ntoa(*(struct in_addr *) &(ip->ip_src))); を配列に代入していきたいのですが上手くいきません。一応自分でやってみたのですが、 void print_ip(struct ip *ip) { int *pa[2048]; static int i = 1; printf("| Source IP Address: %15s|\n", inet_ntoa(*(struct in_addr *) &(ip->ip_src))); i++; pa[i] = (int *)&(ip->ip_src); printf("送信先[%d]%15s\n", i, inet_ntoa(*(struct in_addr *) pa[i])); if (i == 10) { for (i = 1; i < 10; i++) { printf("送信先[%d]%15s\n", i, inet_ntoa(*(struct in_addr *) pa[i])); }} } という風にaddres[1]から順にどんどんIPアドレスを格納しようとしたんですがaddres[1]からaddres[10]まで表示するときに全部addres[10]に代入されているIPアドレスが表示されてしまいます。 おそらく配列にIPアドレスが上手く格納できてないんだと思うのですが。C言語初心者なので誰かご教授していただけないでしょうか? 宜しくお願いします。 OSはLinuxです。

質問者が選んだベストアンサー

  • ベストアンサー
  • galluda
  • ベストアンサー率35% (440/1242)
回答No.5

がると申します。 んっと…ちょっと長くなりますのであらかじめお詫びを。 取り合えず上から順番に。 int *pa[2048]; 確保したいものが「struct in_addr *」であるからには(ip->ip_src の構造体の中身をチェック!!)、これは struct in_addr *pa[10]; としたほうがよいでしょう。かつ、今回の例ですと「関数を抜けた後もデータを保持したい」っぽいので、正確には static struct in_addr *pa[10]; と記述されるべきです。 static int i = 1; 直後にインクリメントが入るので、このままですと「配列の添え字が2からスタート」になってしまいます。 ここはやはり static int i = -1; としておくのがよろしいかと。 struct in_addr *inwk; 後ほど使いますのでここで宣言しておきます。 pa[i] = (int *)&(ip->ip_src); まず、キャストで「ポインタを無理やりintとして取得」するよりは、ストレートに「struct in_addr *」として保持したほうがよいです。 また、このままですと参照先が書き換わればデータも書き換わってしまうので(これが「全部addres[10]に代入されているIPアドレスが表示されてしま」う原因です)、ここは別途メモリを確保してデータを固定のものとして保持しておくべきでしょう。 したがって、このようなロジックに置換します(malloc後のfreeをしていないのでご注意を)。 // メモリ領域を新規に確保します inwk = (struct in_addr *)malloc(sizeof(struct in_addr)); // データをコピーします memcpy(inwk, &ip->ip_src, sizeof(struct in_addr)); // データを設定します pa[i] = (struct in_addr *)inwk; if (i == 10) { 添え字が10である場合、個数は11個になってしまいます。なので、10個で表示をしたいようであれば、ここは if (i == 9) { としておくとよいでしょう。 ほぼ同様の理由で for (i = 1; i < 10; i++) { も for (i = 0; i < 10; i++) { にします。 ーー これで概ね問題なく動くかと思います。 全体の関数を記述しておきます。 void print_ip(struct ip *ip) { static struct in_addr *pa[16]; static int i = -1; struct in_addr *inwk; printf("| Source IP Address: %15s|\n", inet_ntoa(*(struct in_addr *) &(ip->ip_src))); i++; inwk = (struct in_addr *)malloc(sizeof(struct in_addr)); memcpy(inwk, &ip->ip_src, sizeof(struct in_addr)); pa[i] = (struct in_addr *)inwk; printf("送信先[%d]%15s\n", i, inet_ntoa(*(struct in_addr *) pa[i])); if (i == 9) { for (i = 0; i < 10; i++) { printf("送信先[%d]%15s\n", i, inet_ntoa(*(struct in_addr *) pa[i])); } } } まだまだ問題点は山積みですが、取り合えず意図する程度の動きはするのではないかと思いますが、どうでしょうか?

zunzunzunzunzun
質問者

お礼

回答ありがとうございます。こちらの意図するようにプログラムが動いてくれました。貴重な時間、感謝いたします。ありがとうございました!

すると、全ての回答が全文表示されます。

その他の回答 (5)

  • mac_res
  • ベストアンサー率36% (568/1571)
回答No.6

paがstaticになってません。これじゃデーターをためられない。 #include <netinet/ip_icmp.h> #include <arpa/inet.h> #include <stdio.h> #include <errno.h> void print_ip(struct ip *ip) { static struct in_addr pa[11]; static int i = 0; i++; pa[i] = ip->ip_src; printf("送信先[%2d]%15s\n", i, inet_ntoa(pa[i])); if (i == 10) { printf("\n"); for (i = 1; i <= 10; i++) { printf("送信先[%2d]%15s\n", i, inet_ntoa(pa[i])); } } } int main(void) { int i; char buf[16]; struct ip ip; for (i = 0; i < 10; i++) { sprintf(buf, "192.168.0.%d", i + 1); inet_aton(buf, &ip.ip_src); print_ip(&ip); } return 0; }

zunzunzunzunzun
質問者

お礼

おっしゃられた通り、paがstaticになっていませんでした。ご指摘ありがとうございました。上記のプログラムを参考に勉強していこうと思います。ありがとうございました。

すると、全ての回答が全文表示されます。
  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.4

よく見たら、struct in_addr型でpaは配列宣言しないと駄目でしょう。 inet_ntoaに渡すのは、struct in_addr構造体のip_srcメンバです。実体を入れるので、pa[*].ip_srcでアクセスするように修正すれば上手く行くのでは?

zunzunzunzunzun
質問者

お礼

貴重な時間をお使いいただいてありがとうございました。 やはりまだまだ勉強不足を痛感しました。プログラムも思うように動いてくれました。本当に何回も回答していただいてありがとうございました。

zunzunzunzunzun
質問者

補足

こちらの知識不足で申し訳ありません。 おっしゃられていることはこういった感じでよろしいでしょうか?? void print_ip(struct ip *ip) { struct in_addr pa[2048]; static int i = 0; printf("Protocol: IP\n"); printf("+-----+------+------------+-------------------------+\n"); printf("| IV:%1u| HL:%2u| T: %8s| Total Length: %10u|\n", ip->ip_v, ip->ip_hl, ip_ttoa(ip->ip_tos), ntohs(ip->ip_len)); printf("+-----+------+------------+-------+-----------------+\n"); printf("| Identifier: %5u| FF:%3s| FO: %5u|\n", ntohs(ip->ip_id), ip_ftoa(ntohs(ip->ip_off)), ntohs(ip->ip_off) &IP_OFFMASK); printf("+------------+------------+-------+-----------------+\n"); printf("| TTL: %3u| Pro: %3u| Header Checksum: %5u|\n", ip->ip_ttl, ip->ip_p, ntohs(ip->ip_sum)); printf("+------------+------------+-------------------------+\n"); printf("| Source IP Address: %15s|\n", inet_ntoa(*(struct in_addr *) &(ip->ip_src))); printf("+---------------------------------------------------+\n"); printf("| Destination IP Address: %15s|\n", inet_ntoa(*(struct in_addr *) &(ip->ip_dst))); printf("+---------------------------------------------------+\n"); i++; pa[i] = ip->ip_src; printf("送信先[%d]%15s\n", i, inet_ntoa(*(struct in_addr *) pa[i].ip_src)); }

すると、全ての回答が全文表示されます。
  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.3

代入式の方も変更が必要です。 >pa[i] = (int *)&(ip->ip_src); >&(ip->ip_src); では、アドレス入れてます。 pa[i] = ip->ip_src; では?

zunzunzunzunzun
質問者

補足

たびたび申し訳ありません。ご指摘の部分を変えたら代入 に互換性のない型とでてしまいました。

すると、全ての回答が全文表示されます。
回答No.2

外の、変数iのループであるfor文か、while文がないように思いますが、 print_ip関数の全文を提示していただくわけには行かないですか?

zunzunzunzunzun
質問者

補足

print_ip関数はこれで全文なのですが… print_ip関数以外でループ処理をおこなってるみたいなんですが、全文だと800行ぐらいなんですが大丈夫でしょうか? void print_ip(struct ip *ip) { int *pa[2048]; static int i = 0; printf("Protocol: IP\n"); printf("+-----+------+------------+-------------------------+\n"); printf("| IV:%1u| HL:%2u| T: %8s| Total Length: %10u|\n", ip->ip_v, ip->ip_hl, ip_ttoa(ip->ip_tos), ntohs(ip->ip_len)); printf("+-----+------+------------+-------+-----------------+\n"); printf("| Identifier: %5u| FF:%3s| FO: %5u|\n", ntohs(ip->ip_id), ip_ftoa(ntohs(ip->ip_off)), ntohs(ip->ip_off) &IP_OFFMASK); printf("+------------+------------+-------+-----------------+\n"); printf("| TTL: %3u| Pro: %3u| Header Checksum: %5u|\n", ip->ip_ttl, ip->ip_p, ntohs(ip->ip_sum)); printf("+------------+------------+-------------------------+\n"); printf("| Source IP Address: %15s|\n", inet_ntoa(*(struct in_addr *) &(ip->ip_src))); printf("+---------------------------------------------------+\n"); printf("| Destination IP Address: %15s|\n", inet_ntoa(*(struct in_addr *) &(ip->ip_dst))); printf("+---------------------------------------------------+\n"); i++; if (i == 10) { for (i = 1; i < 10; i++) { printf("送信先[%d]%15s\n", i, inet_ntoa(*(struct in_addr *) &(pa[i]))); }} pa[i] = (int *) &(ip->ip_src); printf("送信先[%d]%15s\n", i, inet_ntoa(*(struct in_addr *) &(pa[i]))); }

すると、全ての回答が全文表示されます。
  • t_nojiri
  • ベストアンサー率28% (595/2071)
回答No.1

>int *pa[2048]; って宣言は、paのポインタを格納する配列を2048個作ってるのでは? 宣言を int pa[2048]; にしてみては如何でしょうか?

zunzunzunzunzun
質問者

補足

早速のアドバイスありがとうございます。 ご指摘の部分をint pa[2048]; に変えて見たところ、「代入により、キャストなしでポインタから整数を作りました」と警告が出てしまいました。 勉強不足で申し訳ありません。

すると、全ての回答が全文表示されます。

関連するQ&A