Вот тут задался задачей написать сниффер, нашёл несколько примеров, в
них используется такая конструкция:
/*********** 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. и вопрос в догонку, где можно прочитать о структуре этого буфера,
гуглил, но не смог обнаружить... :(
Заранее спасибо!!!
в эти массивы sprintf пишет строку длиной 17 символов, а на символ '\0' места не хватает, т.е. sprintf вылетает за границы этих буферов, и только благодая положению звезд, этот код не вываливается в сегментатион фаулт. соответственно printf выводит не только содержимое source_addr, но и какой-то мусор за его переделами
и еще не понятно, почему
sizeaddr = 1600;
по-моему, должно быть так
sizeaddr = sizeof(saddr);
и еще, происходит следующее.
если посмотреть на стреса массивов 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.
и еще, происходит следующее.
если посмотреть на стреса массивов 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.
кстати я не понял один момент...размер массива 17, туда записывается 8 элементов по 2 символа что состовляет 16 симвлов, значит 17-ый символ и будет \0...не так?!
Кстати а чем можно конвертнуть хекс формат адресса в обычный формат типа ХХХ.ХХХ.ХХХ.ХХХ?
нет, не так. во первых элементов 6 а не 8, а во вторых ты забыл про 5 дефисов. Итого 6*2+5=17.
а что у тебя там за адреса? Ethernet? Тогда нужно у arp спросить.
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) ???