パケットモニタリング(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です。
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]));
}
}
}
まだまだ問題点は山積みですが、取り合えず意図する程度の動きはするのではないかと思いますが、どうでしょうか?
回答ありがとうございます。こちらの意図するようにプログラムが動いてくれました。貴重な時間、感謝いたします。ありがとうございました!
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;
}
おっしゃられた通り、paがstaticになっていませんでした。ご指摘ありがとうございました。上記のプログラムを参考に勉強していこうと思います。ありがとうございました。
No.4
- 回答日時:
よく見たら、struct in_addr型でpaは配列宣言しないと駄目でしょう。
inet_ntoaに渡すのは、struct in_addr構造体のip_srcメンバです。実体を入れるので、pa[*].ip_srcでアクセスするように修正すれば上手く行くのでは?
この回答への補足
こちらの知識不足で申し訳ありません。
おっしゃられていることはこういった感じでよろしいでしょうか??
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));
}
貴重な時間をお使いいただいてありがとうございました。
やはりまだまだ勉強不足を痛感しました。プログラムも思うように動いてくれました。本当に何回も回答していただいてありがとうございました。
No.2
- 回答日時:
外の、変数iのループであるfor文か、while文がないように思いますが、
print_ip関数の全文を提示していただくわけには行かないですか?
この回答への補足
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])));
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
配列の要素数に変数を入れたい...
-
構造体のextern方法
-
C#で配列が空かを判定するには?
-
MFC - ダイアログボックスのPic...
-
c言語
-
RAW画像高速表示について
-
フィボナッチ数列の求め方
-
C言語において、 配列要素をひ...
-
C言語の穴埋め問題です
-
vector配列の重複を無くすには?
-
MFCのCArrayを使った二次元配列
-
char gyou[1024];でcharの表現...
-
Cプログラムについて
-
C言語 数値の連続入力について
-
AfxBeginThread の引数について
-
define で 配列
-
C#でのフィボナッチ数列
-
C++DLLからC#へのコールバック...
-
int i, int i[1];
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
配列の要素数に変数を入れたい...
-
c言語
-
c言語プログラミング 等差数列...
-
define で 配列
-
構造体のextern方法
-
C#で構造体の配列を持った構造...
-
C言語において、 配列要素をひ...
-
MFC - ダイアログボックスのPic...
-
C言語の2次元配列 容量が大き...
-
2次元配列のマスを数える方法...
-
C言語 ファイルの指定された行...
-
Cのエラー
-
コンボボックスでデフォルト値...
-
C#で配列が空かを判定するには?
-
C#でのフィボナッチ数列
-
ポインタを使って構造体の配列...
-
C言語の課題が出たのですが自力...
-
MFCのCArrayを使った二次元配列
-
C言語の配列のコピーについて
おすすめ情報