Raw Socket Help: Почему UDP-пакеты, созданные необработанными сокетами, не принимаются ядром UDP? - PullRequest
5 голосов
/ 17 апреля 2011

Я изучаю сырые розетки.Я использовал опцию IP_HDRINCL для создания своих собственных заголовков IP.После заголовка IP я создаю заголовок UDP.Затем я отправляю пакет на адрес обратной связи моей системы.У меня запущена другая программа, которая будет перехватывать UDP-пакеты по мере их поступления.Чтобы проверить, правильно ли формируются и принимаются пакеты, у меня запущен другой процесс, который считывает необработанные дейтаграммы IP.Моя проблема в том, что хотя второй процесс (чтение необработанных дейтаграмм) работает хорошо (кажется, что все поля IP и UDP в порядке), но первый процесс (получение UDP) не получает ни один из созданных мной пакетов.Поле протокола в заголовке IP в порядке, и порт также совпадает ... Я использую Linux 2.6.35-22.Я хочу знать, нормально ли это в новых ядрах?Пожалуйста, проверьте код ниже на наличие ошибок.Процесс UDP, который должен получать пакеты, прослушивает сокет, связанный с портом 50000 на той же машине ...

unsigned short in_cksum(unsigned short *addr, int len)
{
    int nleft = len;
    int sum = 0;
    unsigned short *w = addr;
    unsigned short answer = 0;

    while (nleft > 1) {
        sum += *w++;
        nleft -= 2;
    }

    if (nleft == 1) {
        *(unsigned char *) (&answer) = *(unsigned char *) w;
        sum += answer;
    }

    sum = (sum >> 16) + (sum & 0xFFFF);
    sum += (sum >> 16);
    answer = ~sum;
    return (answer);
}


main()
{
    int fd=socket(AF_INET,SOCK_RAW,IPPROTO_UDP);

    int val=1;

    int ret=setsockopt(fd,IPPROTO_IP,IP_HDRINCL,&val,sizeof(val));

    char buf[8192];

    /* create a IP header */

    struct iphdr* ip=(struct iphdr*)buf;//(struct iphdr*) malloc(sizeof(struct iphdr));

    ip->version=4;
    ip->ihl=5;
    ip->tos=0;
    ip->id=0;
    ip->frag_off=0;
    ip->ttl=255;
    ip->protocol=IPPROTO_UDP;
    ip->check=0;
    ip->saddr=inet_addr("1.2.3.4");
    ip->daddr=inet_addr("127.0.0.1");


    struct udphdr* udp=(struct udphdr*)(buf+sizeof(struct iphdr));//(struct udphdr*) malloc(sizeof(struct udphdr));
    udp->source=htons(40000);   
    udp->dest=htons(50000);
    udp->check=0;
    char* data=(char*)buf+sizeof(struct iphdr)+sizeof(struct udphdr);strcpy(data,"Harry Potter and the Philosopher's Stone");
    udp->len=htons(sizeof(struct udphdr)+strlen(data));
    udp->check=in_cksum((unsigned short*) udp,8+strlen(data));

    ip->tot_len=htons(sizeof(struct iphdr)+sizeof(struct udphdr)+strlen(data));

    struct sockaddr_in d;
    bzero(&d,sizeof(d));
    d.sin_family=AF_INET;
    d.sin_port=htons(50000);
    inet_pton(AF_INET,"localhost",&d.sin_addr.s_addr);
    while(1)
     sendto(fd,buf,sizeof(struct iphdr)+sizeof(struct udphdr)+strlen(data),0,(struct sockaddr*) &d,sizeof(d));
}   

Ответы [ 2 ]

3 голосов
/ 08 августа 2012

Кажется, есть проблема с вычислением контрольной суммы UDP.

udp->check=in_cksum((unsigned short*) udp,8+strlen(data));

Контрольная сумма UDP должна включать в себя что-то, называемое «псевдо-заголовком» перед заголовком UDP. Код вычисляет контрольную сумму только для заголовка UDP и полезной нагрузки. Процесс приема UDP может не получать пакеты из-за неправильных контрольных сумм.

Включите проверку контрольной суммы в Wireshark и проверьте правильность полей контрольной суммы пакетов UDP.

См. Следующее:

0 голосов
/ 28 апреля 2011

Я пробовал что-то очень похожее.Проблема состоит в том, что API сокетов и, следовательно, любые программы, которые их используют, не возвращают данные, которые пишутся интерфейсом, в отличие от необработанных сокетов, используемых снифферами, такими как wiresharks / tcpdump.Таким образом, даже если ваши пакеты сформированы правильно, они не читаются приложением UDP.Если у вас есть другой компьютер в сети, используйте один для генерации трафика, а другой - для его чтения.В качестве альтернативы, если у вас два интерфейса, вы можете открыть необработанный сокет на каждом ... один для записи, а другой для чтения.

...