получение ip-адреса пакета в файле pcap

Я программирую с помощью ‘winpcap’, я читаю файл «.pcap» в своей программе, и после этого я хочу получить IP-адреса пакетов, я написал этот код для получения IP-адресов, вот часть моего кода :

  struct sniff_ip {
u_char ip_vhl;      /* version << 4 | header length >> 2 */
u_char ip_tos;      /* type of service */
u_short ip_len;     /* total length */
u_short ip_id;      /* identification */
u_short ip_off;     /* fragment offset field */
#define IP_RF 0x8000        /* reserved fragment flag */
#define IP_DF 0x4000        /* dont fragment flag */
#define IP_MF 0x2000        /* more fragments flag */
#define IP_OFFMASK 0x1fff   /* mask for fragmenting bits */
u_char ip_ttl;      /* time to live */
u_char ip_p;        /* protocol */
u_short ip_sum;     /* checksum */
struct in_addr ip_src;
struct in_addr ip_dst; /* source and dest address */struct sniff_tcp {
u_short th_sport;   /* source port */
u_short th_dport;   /* destination port */
u_int32_t th_seq;       /* sequence number */
u_int32_t th_ack;       /* acknowledgement number */};

и после этого я читаю файл:

while (pcap_next_ex(handler, &header, &packet) >= 0)
{

ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + size_ip);

printf("src port: %d dest port: %d \n", tcp->th_sport, tcp->th_dport);
fprintf(fp,"src port: %d dest port: %d \n", tcp->th_sport, tcp->th_dport);

printf("src address: %s dest address: %s \n",  inet_ntoa(ip->ip_src),  inet_ntoa(ip->ip_dst));
fprintf(fp,"src address: %s dest address: %s \n",  inet_ntoa(ip->ip_src),  inet_ntoa(ip->ip_dst));

printf("seq number: %u ack number: %u \n", (unsigned int)tcp-> th_seq, (unsigned int)tcp->th_ack);
fprintf(fp,"seq number: %u ack number: %u \n", (unsigned int)tcp-> th_seq, (unsigned int)tcp->th_ack);

но адреса источника и Ip одинаковы !!! и он неверно печатает порт источника и назначения !! в чем проблема? что мне делать для этого? плз, помогите мне.

1

Решение

Исходный и целевой порты находятся в сетевой порядок байтов (Большой обратный порядок байт). использование ntohs чтобы получить их в правильном порядке байтов для вашей машины. То же самое касается SEQ и ACK, используйте ntohl для тех.
Размер заголовка IP не всегда может быть 20, умножьте значение ip_hdr_len с 4 чтобы получить реальный размер.

Если ваш компилятор поддерживает битовые поля, вы можете использовать их для объявления заголовка IP, чтобы упростить процесс:

struct sniff_ip {
u_char ip_hdr_len:4;
u_char ip_ver:4;

Фиксированный код:

while (pcap_next_ex(handler, &header, &packet) >= 0) {
ip = (struct sniff_ip*)(packet + SIZE_ETHERNET);

if (ip->ip_p == 6 /* tcp protocol number */) {
tcp = (struct sniff_tcp*)(packet + SIZE_ETHERNET + ip->ip_hdr_len * 4);

u_short srcport = ntohs(tcp->th_sport);
u_short dstport = ntohs(tcp->th_dport);
printf("src port: %d dest port: %d \n", srcport, dstport);

char srcname[100];
strcpy(srcname, inet_ntoa(ip->ip_src));
char dstname[100];
strcpy(dstname, inet_ntoa(ip->ip_dst));
printf("src address: %s dest address: %s \n", srcname, dstname);

u_long seq = ntohl(tcp->th_seq);
u_long ack = ntohl(tcp->th_ack);
printf("seq number: %u ack number: %u \n", seq, ack);
}
}

Обратите внимание, что не каждый пакет будет содержать данные TCP, если вы не применили фильтр, используя pcap_compile а также pcap_setfilter или можете убедиться, что файл, который вы читаете, содержит только пакеты TCP. Поэтому вы можете проверить значение поля протокола заголовков IP, которое будет 6 (TCP), как видно из приведенного выше кода.

Также обратите внимание, что Wireshark по умолчанию отображает относительные номера SEQ и ACK, поэтому они не будут совпадать с тем, что вы видите там.

Структура упаковки должна быть в порядке.

3

Другие решения

Как упаковать структуры зависит от вашего компилятора; например, gcc использует #pragma pack(), Google для pack pragma gcc или же pack pragma visual c или какой компилятор вы используете.

Вам нужно сохранить результаты inet_ntoa, если вы дважды вызываете его для printf, как в

char *srcname=strdup(inet_ntoa(ip->ip_src));
char *dstname=strdup(inet_ntoa(ip->ip_dst));
printf("src address: %s dest address: %s \n", srcname, dstname);
free(srcname);
free(dstname);

(Обратите внимание, что вы должны добавить проверку ошибок, указатели результата функции могут быть NULL).

0

inet_ntoa () возвращает строку точек и чисел в статическом буфере, который перезаписывается при каждом вызове функции.

-1
По вопросам рекламы [email protected]