Roberval Sena 山本 Roberval Sena 山本 - 2 months ago 6
C Question

How to read one .CAP file with C?

My code in C/C++, shoud read some data from a .CAP file, (by the TCPDUMP). One good example could be by WireShark, but I need realy less data.

This .CAP seems to be writen in HEXA and, when I try to read it, the variables are coming "codified" ?!?!

Well, I just a newbee and I have to learn this, I think I am not able to make the correct question... soo, I count on friends good wills to figure it out..

Another Issue is I am totaly lost in an ocean of links in the net... and I just get more confuses...

Explain:
in this link you can get the .CAP, That can be easyli open by WireShark.

Following, my code below... pop ups "strange caracters".

like:

==> revision: �ò�*



OR

==> header_pad: ò�



where "revision", for exemple shound be 12 HEXA or converted 18 decimal


  • Wel, I tryed to coment the code and, this soppouse to run in linux terminal.



.

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
// #include <curses.h>

// テスト用フラグ => Test for the flag
int LOOP_ONCE = 1;

// WiFi取得情報構造体 => get information structure

// Radiotap Header
// 18bytes固定長(と思われる)=> fixed length (seems to be)
typedef struct WF_HEADER
{
char header_revision[1];
char header_pad[1];
unsigned short int header_length;
char present_flags[4];
char flags[1];
char data_rate[1];
char channel_frequency[2];
char channel_flags[2];
char ssi_signal[1];
char antenna[1];
char rx_flags[2];
} wf_header_t;

// IEEE802.11 Probe Request (前半部分)=> (first half)
// 24bytes固定長 => fixed length
typedef struct WF_PROBE1
{
char frame_control_field[4];
char receiver_address[6];
char transmitter_address[6];
char bbs_id[6];
char numbers[2];
} wf_probe1_t;

// IEEE802.11 Probe Request(後半部分)=> (the latter part)
// 4bytes固定長 => fixed length
typedef struct WF_PROBE2
{
char frame_check_sequence[4];
} wf_probe2_t;

// IEEE802.11 wireless LAN management frame(繰り返しヘッダー) => (repeat header)
// 2bytes
typedef struct WF_MANAGE_HEADER
{
char tag_number[1];
char tag_length[1];
} wf_manage_header_t;


int main(int argc, char *argv[]){
char read_fname[30]; //読み込みファイル名 => read file name
int read_fb; //読み込みファイルバンドル => read file bundle
wf_header_t *wfh; //WiFiデータ読み込み構造体のポインタ => pointer of WiFi data read structure
int read_size; //読み込みファイルサイズ => read file size
int wfh_size; // Wifiデータ構造体のサイズ => Wifi data structure; int wfh_size

/* WiFiデータ読み込み構造体の領域確保 => Area of ​​WiFi data read structure ensure */
wfh_size = sizeof(wf_header_t);
wfh = calloc(1, wfh_size);

/* ループ実行 */
/* Loop execution */
while (1) {
/* ファイルの存在を監視する => To monitor the presence of the file */
/* 読み込みファイル名取得 => Read file name acquisition */
if (1) {

system("clear");

// テスト用プログラム => Test program
fprintf(stdout, "読み込みファイル名を入力してください。\n"); // Please enter the reading file name
scanf("%s", read_fname);
fprintf(stdout, "ファイル名:%s\n", read_fname); //file name:
} else {
// 次のファイル名を取得するような仕組み => Like to get the following file name mechanism


}
/* ファイルオープン処理 => Seek to the data top position */
read_fb = open(read_fname, O_RDONLY);
if (read_fb == -1) {
fprintf(stderr, "ファイルオープンに失敗しました。\n"); //Failed to open file
fprintf(stderr, "ファイル名:%s\n", read_fname); //file name
return -1;
}

/* データ先頭位置までシークする => Seek to the data top position * /
/* 前ファイルの続きである場合は、そのまま残サイズを読み込む => Case is a continuation of the previous file, as it is read in the remaining size */

read_size = read(read_fb, wfh, wfh_size);
if (read_size == -1) {
/* ファイル読み込み失敗 => File read failure */
free(wfh);
fprintf(stderr, "ファイル読み込みに失敗しました。\n"); //failed to file read
fprintf(stderr, "ファイル名:%s\n", read_fname); //file name
return -1;
} else if (read_size == wfh_size) {
fprintf(stdout, "====================================\n");
fprintf(stdout, "revision: %s \n", wfh->header_revision);
fprintf(stdout, "header_pad: %s \n", wfh->header_pad);
fprintf(stdout, "present_flags: %s \n", wfh->present_flags);
fprintf(stdout, "flags: %s \n", wfh->flags);
fprintf(stdout, "data_rate: %s \n", wfh->data_rate);
fprintf(stdout, "channel_frequency: %s \n", wfh->channel_frequency);
fprintf(stdout, "channel_flags: %s \n", wfh->channel_flags);
fprintf(stdout, "ssi_signal: %s \n", wfh->ssi_signal);
fprintf(stdout, "antenna: %s \n", wfh->antenna);
fprintf(stdout, "rx_flags: %s \n", wfh->rx_flags);
fprintf(stdout, "====================================\n");



} else {
/* 残りサイズを読み込み、次のファイルへ進む => Read the remaining size, advance to the next file */


}


/* 終了処理 End processing */
if (close(read_fb) != -1) {
// ファイルクローズに成功したので、バックアップフォルダへ移動させる
// Since successful file close, move to the backup folder

} else {
free(wfh);
fprintf(stderr, "ファイルクローズに失敗しました。\n"); // file close failed
fprintf(stderr, "ファイル名:%s\n", read_fname); // file name
return -1;
}
/* ループ終了判定 => Loop termination determination */
if (LOOP_ONCE == 1) {
free(wfh);
fprintf(stdout, "終了しました。\n"); // was completed
return 0;
}
}
}


Thanks for all tips an help ! !

Answer

You do know that in C a string is a sequence of characters terminated by the special character '\0'?

If you print a single character as a string, the printf function will loop printing characters until it finds the terminator character, and that will be beyond the limits of your one-character arrays. That leads to undefined behavior.

The simple solution is to not use arrays for structure members that are not really arrays (I mean all those one-element arrays). And then to use the proper printf format conversion specifier to print the characters. The correct specifier is either "%c" if you want to print it as a character, or "%hhd" if you want to print it as a small integer number.

For more information about the printf format specifiers, please read e.g. this printf (and family) reference.