Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: ubuntu 10.04 + raw sockets  (Прочитано 11223 раз)
0 Пользователей и 1 Гость смотрят эту тему.
Redeemer
Новенький

by
Offline Offline

« : 12-12-2010 16:30 » 

пишу генератор трафика на с++ в linux (ubuntu 10.04)

написал, но пакеты не отправляются вот код:
Код: (C++)

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <iostream>
#include <string.h>
#include <cstdlib>
#define PING_OF_DEATH 1400
using namespace std;


unsigned short CRC32(unsigned short* buffer,int size)
{
unsigned long crc=0;
while(size>1)
{
 crc+=*buffer++;
 size-=sizeof(unsigned short);
 }
 if(size)
 {
 crc+=*(unsigned char*)buffer;
 }
 crc=(crc>>16)+(crc&0xffff);
 crc+=crc>>16;
 return (unsigned short)(~crc);
 }
 
 
 void SETTINGS(char* SRC,char*DST)                                  
{
char* buffer=new char[sizeof(iphdr)+sizeof(icmp)+PING_OF_DEATH];
 struct iphdr* IPHDR=(struct iphdr*)buffer;
 struct icmp* ICMPHDR=(struct icmp*)(buffer+sizeof(iphdr));
 
sockaddr_in Address;
 Address.sin_family=PF_INET;
Address.sin_addr.s_addr=inet_addr(DST);

 int SOcket;


 SOcket=socket(PF_INET,SOCK_RAW,IPPROTO_RAW);
 if(SOcket<0)
 {
cerr<<endl<<"ERROR of init: "<<endl;
}
int opt=1;
int l;

l=setsockopt(SOcket,IPPROTO_IP,IP_HDRINCL,&opt,sizeof(opt));
if(l<0)
cerr<<endl<<"ERROR of option: "<<endl;

l=setsockopt(SOcket,SOL_SOCKET,SO_BROADCAST,&opt,sizeof(opt));
if(l<0)
cerr<<endl<<"ERROR of option: "<<endl;

 //IP header fields
 IPHDR->ihl=5;
 IPHDR->tos=0;
 IPHDR->tot_len=htons(sizeof(ip)+sizeof(icmp)+PING_OF_DEATH);
 IPHDR->id=0;
 IPHDR->frag_off=0;
 IPHDR->ttl=255;
 IPHDR->version=4;
 IPHDR->protocol=IPPROTO_ICMP;
 IPHDR->check=0;
 IPHDR->saddr=inet_addr(SRC);
 IPHDR->daddr=inet_addr(DST);
 IPHDR->check=CRC32((unsigned short*)IPHDR,sizeof(ip));
 
 
 
 ICMPHDR->icmp_type=ICMP_ECHO ;
 ICMPHDR->icmp_code=0 ;
 ICMPHDR->icmp_cksum=0;;
 ICMPHDR->icmp_id=1;
 ICMPHDR->icmp_seq=1;
 ICMPHDR->icmp_cksum=CRC32((unsigned short*)ICMPHDR,(sizeof(icmp)+PING_OF_DEATH));



int sendErr = sendto(SOcket,buffer,sizeof(buffer),0,(struct sockaddr*)&Address,sizeof(Address));
        if(sendErr<0)
        cerr<<endl<<"Error of send: "<<endl;
 
 
 }
 
 int main(int argc,char*argv[])
 {


 char* SRC=new char[17];
char* DST=new char[17];
cout<<"source address: ";
cin.getline(SRC,17);
cout<<"dest address: ";
cin.getline(DST,17);
SETTINGS(SRC,DST);
setuid(getuid());

return 0;
}

При отправке выдает ошибку в функции sendto
когда уменьшаю значение IPHDR->ihl до 1 wireshark на этом же компе его перехватывает, но отображает только первое поле version=4 и header length=4 bogus must be at least 20

я понимаю, что проблема в параметре длина заголовка!!!





Программу запускаю с правами root (sudo -s)


при этом dmesg выводит сообщение
segfault at 0 ip 006b2103 sp bfde3550 error 6 in libstdc++.so.6.0.13[63e000+e9000]
« Последнее редактирование: 12-12-2010 16:36 от RXL » Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #1 : 12-12-2010 16:36 » new

Redeemer, смотри код ошибки и ее описание.

P.S.: это не код - это свалка. Читать это невозможно.

Поправил тег.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Serg79
Команда клуба

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 28-12-2010 11:13 » 

Redeemer, как-то криво ты сокет открываешь для записи сырых данных в него. Какой код ошибки возвращается 'errno'?

Если ты открываешь RAW сокет а функцию маршрутизации пакетов полностью перекладываешь на ядро, то там есть какие то тонкости, в IP_HDR по моему src-ip указывать не надо, и crc в ip-hdr то же формировать не надо. Сейчас соответствующей документации у меня нет под рукой.


Вот посмотри пример, программа читает pcap-dump и выкидывает его содержимое в интерфейс (eth0, ...). Pcap-dump можно записать 'tcpdump'-ом или 'Wireshark'-ом. Обрати внимание на функцию 'open_eth_dev', она открывает интерфейс для записи в него пакетов из pcapdump-а:
Код: (C)
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>

#include <time.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <netpacket/packet.h>
#include <net/ethernet.h>
#include <net/if.h>

#include <arpa/inet.h>

#include "gentraf.h"

/**
 * Формат PCAP файла имеет следующий вид:
 * +-------------+-------------+-----------+-------------+-----------+---+
 * |Global Header|Packet Header|Packet Data|Packet Header|Packet Data|...|
 * +-------------+-------------+-----------+-------------+-----------+---+
 */


/* Pcap Global Header */
struct pcap_global_head {
        uint32_t magic;           /* магический номер */
        uint16_t version_major;   /* старший номер версии */
        uint16_t version_minor;   /* младший номер версии */
        uint32_t thiszone;        /* корекция времени GMT (временная зона) */
        uint32_t sigfigs;         /* временная погрешность (всегда 0) */
        uint32_t snaplen;         /* длина кадра */
        uint32_t linktype;        /* тип канального уровня (Ethernet, PPP, ...) */
};

/* Pcap Packet Header */
struct pcap_packet_head {
        uint32_t tv_sec;          /* время захвата пакета */
        uint32_t tv_usec;         /* микросекунд от tv_sec захвата пакета */
        uint32_t caplen;          /* колличество байт в блоке данных пакета */
        uint32_t len;             /* размер блока данных пакета */
};

/* Pcap Packet Data */
struct pcap_packet_data {
        struct pcap_packet_head p_head;  /* заголовок пакета */
        unsigned char *packet_data;        /* данные пакета */
};

/* Pcap Data */
struct pcap_file_data {
        struct pcap_global_head p_glob_head;      /* заголовок pcap файла */
        int number_packet_data;                /* количество пакетов */
        struct pcap_packet_data *p_packets;    /* массив пакетов */
};

static void help(void)
{
        fprintf(stderr, "Usage: " PROGNAME " [options] file...\n"
                        "\n"
                        "Options:\n"
                        "  -i [INTERF]    writen on interface\n"
                        "  -s [SEC]       job time in seconds\n"
                        "  -c [COUNT]     cycles to send the file\n"
                        "  -h             view this help\n");
}

static void usage(void)
{
        fprintf(stderr, "Usage: " PROGNAME " [options] -i [eth] file\n");
}

/*
 * Возвращает количество пакетов находящихся
 * в pcap файле.
 */

static int get_number_pcap_packet(FILE *fp)
{
        int number;

        fseek(fp, sizeof(struct pcap_global_head), SEEK_SET);

        for (number = 0;;) {
                struct pcap_packet_head p_packet;
                size_t n;

                n = fread(&p_packet, sizeof(p_packet), 1, fp);
                if (n != 1) {
                        if (!feof(fp)) {
                                err_msg("Failed counting packets of pcap file.");
                                return 0;
                        } else
                                break;
                }

                number++;
                fseek(fp, p_packet.caplen, SEEK_CUR);
        }

        return number;
}

/*
 * Загружает pcap файл в память и возвращает указатель на
 * структуру pcap_file_data содержащую данные из файла.
 */

static struct pcap_file_data *load_pcap_file(const char *pcap_name)
{
        struct pcap_file_data *p_file = NULL;
        struct pcap_global_head p_glob_head;
        int number_packet_data, i;
        FILE *fp;

        if ((fp = fopen(pcap_name, "rb")) == NULL)
                return NULL;

        if (fread(&p_glob_head, sizeof(p_glob_head), 1, fp) != 1)
                goto out;

#define PCAP_MAGIC                0xa1b2c3d4
#define PCAP_VERSION_MAJOR                 2
#define PCAP_VERSION_MINOR                 4
        if (p_glob_head.magic != PCAP_MAGIC ||
                        p_glob_head.version_major != PCAP_VERSION_MAJOR ||
                        p_glob_head.version_minor != PCAP_VERSION_MINOR) {
                err_msg("The '%s' no pcap format file.", pcap_name);
                goto out;
        }

        number_packet_data = get_number_pcap_packet(fp);
        if (!number_packet_data) {
                err_msg("It '%s' not contain pcap data.", pcap_name);
                goto out;
        }

        p_file = xmalloc(sizeof(*p_file));
        p_file->p_glob_head = p_glob_head;
        p_file->p_packets =
                xmalloc(sizeof(*p_file->p_packets) * number_packet_data);

        fseek(fp, sizeof(struct pcap_global_head), SEEK_SET);

        for (i = 0; i < number_packet_data; i++) {
                struct pcap_packet_data *p;
                size_t n;

                p = &p_file->p_packets[i];

                n = fread(&p->p_head, sizeof(p->p_head), 1, fp);
                if (n != 1) {
                        err_msg("Failed load packet head is '%s' pcap file.\n"
                                        "Loading only %d packets one of a %d.",
                                        pcap_name, i, number_packet_data);
                        break;
                }

                p->packet_data = xmalloc(p->p_head.caplen);
                n = fread(p->packet_data, p->p_head.caplen, 1, fp);
                if (n != 1) {
                        err_msg("Failed load packet data is '%s' pcap file.\n"
                                        "Loading only %d packets one of a %d.",
                                        pcap_name, i, number_packet_data);
                        break;
                }
        }
        p_file->number_packet_data = i;

out:
        fclose(fp);

        return p_file;
}

/*
 * Освобождает память выделенную под загруженный pcap файл.
 */

static void free_pcap_file(struct pcap_file_data *p_file)
{
        int i;

        for (i = 0; i < p_file->number_packet_data; i++)
                xfree(p_file->p_packets[i].packet_data);
        xfree(p_file->p_packets);
        xfree(p_file);
}

/*
 * Открывает eth интерфейс для записи в него пакетов.
 */

static int open_eth_dev(const char *eth_name)
{
        int sock;
        struct ifreq ifr;
        struct sockaddr_ll sll;

        sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
        if (sock == -1) {
                err_msg("Failed open RAW socket: %s", strerror(errno));
                return -1;
        }

        memset(&ifr, 0, sizeof(ifr));
        strncpy(ifr.ifr_name, eth_name, sizeof(ifr.ifr_name) - 1);
        if (ioctl(sock, SIOCGIFINDEX, &ifr) == -1) {
                err_msg("ioctl SIOCGIFINDEX error: %s", strerror(errno));
                goto errout;
        }

        memset(&sll, 0, sizeof(sll));
        sll.sll_family = AF_PACKET;
        sll.sll_ifindex = ifr.ifr_ifindex;
        sll.sll_protocol = htons(ETH_P_ALL);
        if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) == -1) {
                err_msg("Failed binding socket: %s", strerror(errno));
                goto errout;
        }

        return sock;

errout:
        close(sock);
        return -1;
}

/*
 * Закрывает eth интерфей.
 */

static void close_eth_dev(int sock)
{
        close(sock);
}

/* флаг указывающий о прекращении работы */
static volatile int flags_exit;

static void sig_func(int signo)
{
        if (signo == SIGINT)
                printf("signal SIGINT\n");
        flags_exit = 1;
}

int main(int argc, char **argv)
{
        const char *fpcap = NULL, *dev = NULL;
        struct pcap_file_data *p_file;
        int oc, sock_dev;
        int count_send = 0, timeout_job = 0;

        prog_name = argv[0];

        while ((oc = getopt(argc, argv, ":i:s:c:h")) != -1) {
                switch (oc) {
                        case 'i':
                                dev = optarg;
                                break;

                        case 's':
                                timeout_job = atoi(optarg);
                                break;

                        case 'c':
                                count_send = atoi(optarg);
                                break;

                        case 'h':
                                help();
                                exit(1);
                                break;

                        case ':':
                                err_quit("option '-%c' requires an argument.", optopt);
                                break;

                        case '?':
                        default:
                                err_quit("option '-%c' is invalid.", optopt);
                                break;
                }
        }

        fpcap = argv[optind];

        if (!dev || !fpcap) {
                usage();
                exit(1);
        }

        if ((p_file = load_pcap_file(fpcap)) == NULL)
                err_quit("Failed load '%s' pcap file.", fpcap);
        if ((sock_dev = open_eth_dev(dev)) == -1)
                err_quit("Failed open '%s' device.", dev);

        if (signal(SIGALRM, sig_func) == SIG_ERR)
                err_quit("Failed setting signal 'SIGALRM': %s", strerror(errno));
        if (signal(SIGINT, sig_func) == SIG_ERR)
                err_quit("Failed setting signal 'SIGINT': %s", strerror(errno));

        if (timeout_job)
                alarm(timeout_job);

        while (!flags_exit) {
                int i;

                for (i = 0; !flags_exit && (i < p_file->number_packet_data); i++) {
                        struct pcap_packet_data *p = &p_file->p_packets[i];
                        size_t n;

                        n = write(sock_dev, p->packet_data, p->p_head.caplen);
                        if (n == -1) {
                                err_quit("Error writing device '%s': %s",
                                                dev, strerror(errno));
                        } else if (n != p->p_head.caplen) {
                                err_msg("WARNING: writing %u of %u in the '%s': %s",
                                                (unsigned)n, p->p_head.caplen, dev, strerror(errno));
                        }
                }

                if (count_send) {
                        if (!--count_send)
                                flags_exit = 1;
                }
        }

        if (timeout_job)
                alarm(0);
        close_eth_dev(sock_dev);
        free_pcap_file(p_file);

        return 0;
}
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines