/*
* File: main.cpp
* Author: root
*
* Created on 25 Июнь 2008 г., 18:28
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
//#include <linux/in.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <memory.h>
#include <sys/fcntl.h>
#include <stdlib.h>
typedef struct IPHeader {
u_char iph_verlen; // версия и длина заголовка
u_char iph_tos; // тип сервиса
u_short iph_length; // длина всего пакета
u_short iph_id; // Идентификация
u_short iph_offset; // флаги и смещения
u_char iph_ttl; // время жизни пакета
u_char iph_protocol; // протокол
u_short iph_xsum; // контрольная сумма
u_long iph_src; // IP-адрес отправителя
u_long iph_dest; // IP-адрес назначения
} IPHeader;
struct UdpHeader
{
u_short src_port;
u_short targ_port;
u_short length;
u_short checksum;
};
int main(int argc, char **argv) {
int sock, n;
int ret;
unsigned char buffer[65536];
unsigned char *ethhead;
struct ifreq ethreq;
IPHeader IPh;
UdpHeader UDPh;
sockaddr_in temp1,temp2;
if ( (sock=socket(PF_PACKET, SOCK_RAW,
htons(ETH_P_IP)))<0) {
perror("socket");
exit(1);
}
/* Set the network card in promiscuos mode */
strncpy(ethreq.ifr_name,"eth1",IFNAMSIZ);
if (ioctl(sock,SIOCGIFFLAGS,ðreq)==-1) {
perror("ioctl");
close(sock);
exit(1);
}
ethreq.ifr_flags|=IFF_PROMISC;
if (ioctl(sock,SIOCSIFFLAGS,ðreq)==-1) {
perror("ioctl");
close(sock);
exit(1);
}
/* set socket to nonblock */
ret = fcntl(sock, F_GETFL);
ret |= O_NONBLOCK;
if ( fcntl(sock, F_SETFL, ret) < 0 ) {
printf("set socket to nonblock fail [%d] !\n", errno);
//goto exit_program;
}
while (1) {
memset(&IPh-14,0,sizeof(IPHeader)+14);
n = recvfrom(sock,buffer,2048,0,NULL,NULL);
if (n>42) {
printf("----------\n");
printf("%d bytes read\n",n);
ethhead = buffer;
printf("Source MAC address: "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
ethhead[0],ethhead[1],ethhead[2],
ethhead[3],ethhead[4],ethhead[5]);
printf("Destination MAC address: "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
ethhead[6],ethhead[7],ethhead[8],
ethhead[9],ethhead[10],ethhead[11]);
memcpy(&IPh,buffer+14,sizeof(IPHeader));
memcpy(&UDPh,buffer+14+sizeof(IPHeader),sizeof(UdpHeader));
memcpy(&temp1.sin_addr.s_addr, &IPh.iph_src,sizeof(in_addr));
memcpy(&temp2.sin_addr.s_addr , &IPh.iph_dest,sizeof(in_addr));
printf("Source IP: %s:%d\n",inet_ntoa(temp1.sin_addr),htons(UDPh.src_port));
printf("Dest IP: %s:%d\n",inet_ntoa(temp2.sin_addr),htons(UDPh.targ_port));
switch (IPh.iph_protocol){
case IPPROTO_TCP:
printf("Protool IPPROTO_TCP\n");
break;
case IPPROTO_UDP:
printf("Protool IPPROTO_UDP\n");
break;
case IPPROTO_ICMP:
printf("Protool IPPROTO_ICMP\n");
break;
default:
printf("Protool %d \n",IPh.iph_protocol);
break;
}
}
}
return (EXIT_SUCCESS);
}
Сырые сокеты. Ошибка с адресами входящими и исходящими
Код:
И еще у меня две сетевухи, как мне перехватиывать только на одной сетевухе? читал в статье про роу сокеты, что если я буду использовать bind тогда я не смогу перехватывать пакеты которые адресованы не мне...
Какой компилятор используете? g++? Вижу в комменте у Вас @main.cpp@, а директивы extern C { ...} где? Вы используете в данном случае "чистый" Си, а в С++ есть классы они позволяют удобно инкапсулировать все то, что Вы вынесли во внешние функции. http://www.proklondike.com/contentview.php?content=471
[QUOTE=WWTLF]И еще у меня две сетевухи, как мне перехватиывать только на одной сетевухе?[/QUOTE]
Libpcap в помощь -> http://sourceforge.net/projects/libpcap/
Более профессиональный подход будет заключаться в использовании библиотеки libpcap, а не мучаться с RAW сокетами. Парадигма проста - для сетевого снифера используем libpcap (тогда уровень фильтрации повыситься до солидного), для соединения с хостами в сети все же лучше будет использование протокола RPC.
Спасибо за книгу...
С проблемой источника и приемника разобрался, ethernet заголовк неверный у меня в коде. Правильный: ПРИЕМНИК ИСТОЧНИК ПРОТОКОЛ. У меня же следуюя обычной человеческой логие сначало источник потом приемник.