Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Сети > пинг


Автор: n1ke 3.12.2006, 22:20
(Заранее извеняюсь за мой русский, эсли будут ошибки)

Всем привет!
У меня такая задача:
Надо послать ICMP пакет (echo), получить отклик (reply) и вывести его на екран! Всё ето надо написать под Linux (gcc).
Подскажите где я ошибся!

Код

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <resolv.h>
#include <unistd.h>    /* For getpid() */

#define MAX_PACKET 1024


int main (int argc, char *argv[])
{
    if (argc != 2){
        printf ("usage: ping <IP>\n");
        return ;
    }
    
    char datagram[1024];
    char recvbuf[1024];
    int sequence = 0;
    int s = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP);
    
    struct icmphdr *icmph = (struct icmphdr *) datagram;
    struct sockaddr_in sin;
    struct sockaddr_in from;
    

    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr (argv[1]);

    memset (datagram + sizeof(struct iphdr), 0, MAX_PACKET - sizeof(struct iphdr));
    icmph->type = ICMP_ECHO;
    icmph->code = 0;
    icmph->checksum = 0;
    icmph->un.echo.id = getpid();   
    icmph->un.echo.sequence = sequence;
  
    if (sendto (s, datagram, MAX_PACKET, 0, &sin, sizeof(sin)) < 0)
        printf ("error\n");
    recvfrom (s, recvbuf, sizeof(recvbuf), 0, (struct sockaddr_in *) &from, sizeof(from));
    printf ("%s\n",recvbuf);
    return 0;
}




Автор: Step 3.12.2006, 22:27
n1ke, а что собственно не так, ошибка при компиляции или чтото не так в алгоритме

Автор: n1ke 4.12.2006, 00:24
Я поменял одну строку в конце:

Код

printf ("Reply from %s\n", inet_ntoa (from.sin_addr.s_addr));


Программа не хочет присылать "reply", зато когда я запускаю прогу с адресом 127.0.0.1 она показывает "reply" c адреса 22.10.102.69 !!!

Что ето за чудо??

Автор: Dude03 4.12.2006, 00:31
Цитата(n1ke @  3.12.2006,  22:20 Найти цитируемый пост)
icmph->checksum = 0;

в винде такой бы пакет не отослался - чексума проверяется при отсылке smile  

Автор: n1ke 4.12.2006, 01:49
Никак не могу разобратся с чексуммой, может кто-нибуть обеснит по детски как она вычисляется (и с примером, если можно)

Автор: ptr 4.12.2006, 09:06
Посмотри http://tangentsoft.net/wskfaq/examples/rawping.html. Там правда для Windows.

Автор: Dude03 4.12.2006, 09:24
Цитата(ptr @  4.12.2006,  09:06 Найти цитируемый пост)
Посмотри здесь. Там правда для Windows. 

Ты же можешь пропинговать с винды никс? Почему тогда должна быть разница в вычислении crc

Автор: ptr 4.12.2006, 09:29
Цитата(Dude03 @  4.12.2006,  12:24 Найти цитируемый пост)
Ты же можешь пропинговать с винды никс? Почему тогда должна быть разница в вычислении crc

А причём здесь я?

Автор: Dude03 4.12.2006, 09:40
Цитата(ptr @  4.12.2006,  09:29 Найти цитируемый пост)
А причём здесь я?

 smile 

Автор: n1ke 4.12.2006, 23:49
Ребята, ну не получается у меня отослать пакет! Проблема заключается в чексумме. Я дописал функцию (нашел в инете) и всёравно никак!
Подскжте где я ошибся плзз !!!

Код

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <resolv.h>
#include <unistd.h>    /* For getpid() */

#define ICMPHDR_SIZE 8
#define MAX_PACKET 64

unsigned short cksum(unsigned short *buf, int nbytes)
{
    unsigned int sum;
    unsigned short oddbyte;

    sum = 0;
    while (nbytes > 1) {
        sum += *buf++;
        nbytes -= 2;
    }

    if (nbytes == 1) {
        oddbyte = 0;
        *((unsigned short *) &oddbyte) = *(unsigned short *) buf;
        sum += oddbyte;
    }

    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);



    return (unsigned short) ~sum;
}


int main (int argc, char *argv[])
{
    if (argc != 2){
        printf ("usage: ping <IP>\n");
        return ;
    }
    
    
    char
        datagram[MAX_PACKET],
        recvbuf[1024];
    
    int
        sequence = 0,
        s = socket (PF_INET, SOCK_RAW, IPPROTO_ICMP),
        datalen = MAX_PACKET - sizeof(struct icmphdr);
    
    struct icmphdr *icmph = (struct icmphdr *)datagram;
    struct sockaddr_in sin;
    struct sockaddr_in from;
    
    bzero (&sin, sizeof(sin));
    sin.sin_family = AF_INET;
    sin.sin_addr.s_addr = inet_addr (argv[1]);
    
    memset (datagram, 0, MAX_PACKET);
    icmph->type = ICMP_ECHO;
    icmph->code = 0;
    icmph->checksum = cksum ((unsigned short *)datagram, MAX_PACKET);
    icmph->un.echo.id = getpid();
    icmph->un.echo.sequence = sequence;
  
    if (sendto (s, datagram, MAX_PACKET, 0, &sin, sizeof(sin)) < 0)
        printf ("error\n");
    recvfrom (s, recvbuf, sizeof(recvbuf), 0, (struct sockaddr_in *) &from, sizeof(from));
    printf ("Reply from %s\n", inet_ntoa (from.sin_addr.s_addr));
    return 0;

}



Автор: Dude03 5.12.2006, 00:29
 smile 
сначала заполняются все поля и чексумма в 0, а потом уже высчитывается чексумма пакета smile 

Автор: bel_nikita 5.12.2006, 00:39
для начала: 
Код

...
struct icmphdr icmph;
...
icmph.checksum = 0;
icmph.type = ICMP_ECHO;
icmph.code = 0;
icmph.un.echo.id = getpid();
icmph.un.echo.sequence = sequence;
icmph.checksum = cksum ( (unsigned short *)&icmph, sizeof(icmph) );
...
if (sendto (s, (char*)&icmph, sizeof(icmph), 0, &sin, sizeof(sin)) < 0) printf ("error\n");
...

Автор: n1ke 5.12.2006, 00:53
Большое спасибо!

Автор: Virun 23.12.2006, 22:26
А можно узнать для чего введена коннстанта ICMPHDR_SIZE? Она ведь нигде не ипользуется =\

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)