全部博文(140)
分类: 网络与安全
2014-03-08 22:23:34
原文地址:linux sock_raw原始套接字编程 作者:spengdong
... |
int set_promisc(char *interface, int fd) { |
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "netinet/ip.h"
#include "netinet/ip_icmp.h"
#include "netdb.h"
#include "errno.h"
#include "arpa/inet.h"
#include "signal.h"
#include "sys/time.h"
extern int errno;
int sockfd;
struct sockaddr_in addr; //peer addr
char straddr[128]; //peer addr ip(char*)
char sendbuf[2048];
char recvbuf[2048];
int sendnum;
int recvnum;
int datalen = 30;
unsigned short my_cksum(unsigned short *data, int len) {
int result = 0;
for(int i=0; i<len/2; i++) {
result += *data;
data++;
}
while(result >> 16)result = (result&0xffff) + (result>>16);
return ~result;
}
void tv_sub(struct timeval* recvtime, const struct timeval* sendtime) {
int sec = recvtime->tv_sec - sendtime->tv_sec;
int usec = recvtime->tv_usec - sendtime->tv_usec;
if(usec >= 0) {
recvtime->tv_sec = sec;
recvtime->tv_usec = usec;
} else {
recvtime->tv_sec = sec-1;
recvtime->tv_usec = -usec;
}
}
void send_icmp() {
struct icmp* icmp = (struct icmp*)sendbuf;
icmp->icmp_type = ICMP_ECHO;
icmp->icmp_code = 0;
icmp->icmp_cksum = 0;
icmp->icmp_id = getpid(); //needn't use htons() call, because peer networking kernel didn't handle this data and won't make different meanings(bigdian litteldian)
icmp->icmp_seq = ++sendnum; //needn't use hotns() call too.
gettimeofday((struct timeval*)icmp->icmp_data, NULL);
int len = 8+datalen;
icmp->icmp_cksum = my_cksum((unsigned short*)icmp, len);
int retval = sendto(sockfd, sendbuf, len, 0, (struct sockaddr*)&addr, sizeof(addr));
if(retval == -1){
perror("sendto()");
exit(-1);
} else {
// printf("send icmp request to %s(%d) bytes"n", straddr, len);
}
}
void recv_icmp() {
struct timeval *sendtime;
struct timeval recvtime;
for(;;) {
int n = recvfrom(sockfd, recvbuf, sizeof(recvbuf), 0, 0, 0);
if(n == -1) {
if(errno == EINTR)continue;
else {
perror("recvfrom()");
exit(-1);
}
} else {
gettimeofday(&recvtime, NULL);
struct ip *ip = (struct ip*)recvbuf;
if(ip->ip_src.s_addr != addr.sin_addr.s_addr) {
// printf("ip_src is not : %s"n", straddr);
continue;
}
struct icmp *icmp = (struct icmp*)(recvbuf + ((ip->ip_hl)<<2));
if(icmp->icmp_id != getpid()) {
// printf("icmp_id is not :%d"n", getpid());
continue;
}
recvnum++;
sendtime = (struct timeval*)icmp->icmp_data;
tv_sub(&recvtime, sendtime);
printf("imcp echo from %s(%dbytes)"tttl=%d"tseq=%d"ttime=%d.%06d s"n", straddr, n, ip->ip_ttl, icmp->icmp_seq, recvtime.tv_sec, recvtime.tv_usec);
}
}
}
void catch_sigalrm(int signum) {
send_icmp();
alarm(1);
}
void catch_sigint(int signum) {
printf(""nPing statics:send %d packets, recv %d packets, %d%% lost..."n", sendnum, recvnum, (int)((float)(sendnum-recvnum)/sendnum)*100);
exit(0);
}
int main(int argc, char **argv) {
if(argc != 2) {
printf("please use format: ping hostname"n");
exit(-1);
}
sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
if(sockfd == -1) {
perror("socket()");
return -1;
}
/*
int sendbufsize = 180;
socklen_t sendbufsizelen = sizeof(sendbufsize);
if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &sendbufsize, sendbufsizelen) == -1)perror("setsockopt()");
int recvbufsize;
socklen_t recvbufsizelen;
if(getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &recvbufsize, &recvbufsizelen) == -1)perror("getsockopt()");
*/
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
int retval = inet_pton(AF_INET, argv[1], &addr.sin_addr);
if(retval == -1 || retval == 0) {
struct hostent* host = gethostbyname(argv[1]);
if(host == NULL) {
fprintf(stderr, "gethostbyname(%s):%s"n", argv[1], strerror(errno));
exit(-1);
}
/*
if(host->h_name != NULL)printf("hostent.h_name:%s"n", host->h_name);
if(host->h_aliases != NULL && *(host->h_aliases) != NULL)printf("hostent.h_aliases:%s"n", *(host->h_aliases));
printf("hostent.h_addrtype:%d"n", host->h_addrtype);
printf("hostent.h_length:%d"n", host->h_length);
*/
if(host->h_addr_list != NULL && *(host->h_addr_list) != NULL) {
strncpy((char*)&addr.sin_addr, *(host->h_addr_list), 4);
inet_ntop(AF_INET, *(host->h_addr_list), straddr, sizeof(straddr));
}
printf("Ping address:%s(%s)"n"n", host->h_name, straddr);
} else {
strcpy(straddr, argv[1]);
printf("Ping address:%s(%s)"n"n", straddr, straddr);
}
struct sigaction sa1;
memset(&sa1, 0, sizeof(sa1));
sa1.sa_handler = catch_sigalrm;
sigemptyset(&sa1.sa_mask);
sa1.sa_flags = 0;
if(sigaction(SIGALRM, &sa1, NULL) == -1)perror("sigaction()");
struct sigaction sa2;
memset(&sa2, 0, sizeof(sa2));
sa2.sa_handler = catch_sigint;
sigemptyset(&sa2.sa_mask);
sa2.sa_flags = 0;
if(sigaction(SIGINT, &sa2, NULL) == -1)perror("sigaction()");
alarm(1);
recv_icmp();
return 0;
}
yandongxiao2014-03-13 21:00:19
http://hi.baidu.com/zkheartboy/item/ce93ff0c58d91d6cd45a1134 have a totally corrent code
yandongxiao2014-03-13 20:57:53
/*
编译时遇到的问题:
1、Unresolved inclusion: sys/types.h。解决办法:find / | grep sys.types.h. 找到了
该文件的位置。结合http://blog.csdn.net/psvoldemort/article/details/6961067对
C_INCLUDE_PATH的操作可知:改变为#include <i386-linux-gnu/sys/types.h>
2、‘ETH_P_ALL’未声明。解决办法:grep ETH_P_ALL /usr/include/linux , 巨牛逼的命令。
/usr/include/linux/if_ether.h:#define ETH_P_ALL 0x0003
输出关键字ETH_P_ALL所在的行,以及ETH_P_ALL坐在的文件。
3、对于sockaddr_ll 所在头文件的查找。grep s