LINUX.ORG.RU

recvfrom(sd, buf, 1600, 0, &saddr, &sizeaddr);


0

0

Вот тут задался задачей написать сниффер, нашёл несколько примеров, в
них используется такая конструкция:

/*********** prog1.cpp ***********************/

unsigned char buf[1600];

void init()
{
       int sd;
       socklen_t sizeaddr;
       struct sockaddr saddr;

       sizeaddr = 1600;

       while (1){
		length = recvfrom(sd, buf, 1600, 0, &saddr, &sizeaddr);
		if (length == -1)continue;
		handle(buf, length, &saddr);
	}
}

и затем:

void handle(unsigned char buf[], int length, struct sockaddr *saddr)
{
	char dest_addr[17];
	char source_addr[17];
	unsigned int type_len;
 sprintf(source_addr,"%02X-%02X-%02X-%02X-%02X-%02X",buf[6],buf[7],buf[
8],\
 		buf[9],buf[10],buf[11]);
sprintf(dest_addr,"%02X-%02X-%02X-%02X-%02X-%02X",buf[0],buf[1],buf[2]
,\
		buf[3],buf[4],buf[5]);

	if ((strcmp(dest_addr,target) == 0 ) | (strcmp(source_addr, target) == 0\
		| (strcmp(target,"FF-FF-FF-FF-FF-FF") == 0)))
	{
		printf("%s -> %s: ",source_addr, dest_addr);
	}
...
}
/*********** end prog1.cpp ***********************/

а вот вопрос такой, почему на выводе я вижу

00-0B-CD-1A-84-E7FF-FF-FF-FF-FF-FF -> FF-FF-FF-FF-FF-FF
00-12-A9-F7-52-B801-80-C2-00-00-00 -> 01-80-C2-00-00-00
00-16-E6-45-58-C0FF-FF-FF-FF-FF-FF -> FF-FF-FF-FF-FF-FF
00-01-03-31-EC-C3FF-FF-FF-FF-FF-FF -> FF-FF-FF-FF-FF-FF

интересует вот этот кусок

00-16-E6-45-58-C0FF-FF-FF-FF-FF-FF -> FF-FF-FF-FF-FF-FF

а ищё конкретнее

00-16-E6-45-58-C0FF-FF-FF-FF-FF-FF

откуда берётся этот хвост FF-FF-FF-FF-FF-FF.
Как я проверил он лежит в buf[11], т.е. когда я убераю его то и этот
хвост не выводится. К тому же получается что этот хвост лежит в одном
элементе массива.

В чём засада и как это можно пофиксить?!

P.S. и вопрос в догонку, где можно прочитать о структуре этого буфера,
гуглил, но не смог обнаружить... :(

Заранее спасибо!!!
★★★★★

код ужасен.

если собираешь писать сниффер, смотри в сторону libpcap, не изобретай свой велосипед.

anonymous
()
Ответ на: комментарий от anonymous

Да причём тут ужасен, я просто вырезал и вставил, для того что бы понять суть. Так в чём же причина?!

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

так, на вскидку, может ошибаюсь:

char dest_addr[17];
char source_addr[17];

в эти массивы sprintf пишет строку длиной 17 символов, а на символ '\0' места не хватает, т.е. sprintf вылетает за границы этих буферов, и только благодая положению звезд, этот код не вываливается в сегментатион фаулт. соответственно printf выводит не только содержимое source_addr, но и какой-то мусор за его переделами

и еще не понятно, почему
sizeaddr = 1600;
по-моему, должно быть так
sizeaddr = sizeof(saddr);

anonymous
()
Ответ на: комментарий от anonymous

и еще, происходит следующее. если посмотреть на стреса массивов source_addr, dest_addr, то массив dest_addr в памяти размещается сразу за source_addr. (я на практике не проверял, не компилил, но так оно и будет в данном конкретном примере) а теперь по шагам твоего алгоритма

1. загоням строку в массив source_addr, крайний символ этой строки '\0' не умещается массиве source_addr и залезает в dest_addr[0] 2. загоням строку в массив dest_addr, конечно же символ '\0' в dest_addr[0] затирается. У строки, которую пишем в dest_addr, крайний символ '\0' не умещается в массив dest_addr и залезает в dest_addr[17], хотя максимальное допустивое смещение в этом массиве dest_addr[16], т.е. мы вышли за границы dest_addr, и крайний символ записалса хрен знает куда (видимо в type_len). что мы получили, по сути строка source_addr - это конкатенация массива source_addr и dest_addr 3. при выводе printf-ом массива source_addr воводится содержимое source_addr и dest_addr. при выводе printf-ом массива dest_addr воводится содержимое только dest_addr.

cyclon делись звездами

anonymous
()
Ответ на: комментарий от anonymous

и еще, происходит следующее.
если посмотреть на стреса массивов source_addr, dest_addr, то массив dest_addr в памяти размещается сразу за source_addr. (я на практике не проверял, не компилил, но так оно и будет в данном конкретном примере) а теперь по шагам твоего алгоритма

1. загоням строку в массив source_addr, крайний символ этой строки '\0' не умещается массиве source_addr и залезает в dest_addr[0]
2. загоням строку в массив dest_addr, конечно же символ '\0' в dest_addr[0] затирается. У строки, которую пишем в dest_addr, крайний символ '\0' не умещается в массив dest_addr и залезает в dest_addr[17], хотя максимальное допустивое смещение в этом массиве dest_addr[16], т.е. мы вышли за границы dest_addr, и крайний символ записалса хрен знает куда (видимо в type_len).
что мы получили, по сути строка source_addr - это конкатенация массива source_addr и dest_addr
3. при выводе printf-ом массива source_addr воводится содержимое source_addr и dest_addr. при выводе printf-ом массива dest_addr воводится содержимое только dest_addr.

cyclon делись звездами

anonymous
()
Ответ на: комментарий от anonymous

я уже почти год не писал никаких прог на сях так что принял код который нашёл на веру :))

Пы.Сы. так что звёзды не отдам :)))

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

кстати я не понял один момент...размер массива 17, туда записывается 8 элементов по 2 символа что состовляет 16 симвлов, значит 17-ый символ и будет \0...не так?!

Кстати а чем можно конвертнуть хекс формат адресса в обычный формат типа ХХХ.ХХХ.ХХХ.ХХХ?

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

нет, не так. во первых элементов 6 а не 8, а во вторых ты забыл про 5 дефисов. Итого 6*2+5=17. а что у тебя там за адреса? Ethernet? Тогда нужно у arp спросить.

cobold ★★★★★
()
Ответ на: комментарий от cyclon

в общем длина твоих массивов должна быть 18 байт, 17 байт под саму строку и 1 байт для символа '\0'

char dest_addr[18];
char source_addr[18];

и все выводится будет нормально

> чем можно конвертнуть хекс формат адресса в обычный формат типа ХХХ.ХХХ.ХХХ.ХХХ?
если речь идет о IP-адресе, то inet_ntop

anonymous
()
Ответ на: комментарий от anonymous

const char *inet_ntop(int af, const void *src,
                             char *dst, socklen_t cnt);

А что надо передавать в inte_ntop в качестве src, т.е. какую часть buf или надо весь buf с размером sizeaddr?!

inet_ntop(AF_INET,(void*)buf,ip,sizeaddr) ???

cyclon ★★★★★
() автор топика
Ответ на: комментарий от cyclon

У тебя же 6 октетов, а ты пытаешься получить IPv4 адрес. Это либо IPv6 либо MAC. IP+port там быть не может т.к. они в пакете идут не подряд.

cobold ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.