[완료]raw socket 관련문제입니다,,
글쓴이: revol2236 / 작성시간: 수, 2010/01/27 - 4:33오전
며칠 전부터 raw socket에서 ping을 구현하고 있는 한 학생입니다,,
그런데 ping 에는 s 옵션이 있어서 보낼 ping size를 정해서 보낼수있더군요,,;;
일단 저도 그것을 구현하기 위해서 ip_off멤버에 손을 대서 어떻게 어떻게 MF 플래그를 포함하여 offset정도는 맞출수 있게 되었습니다,,
그런데 wireshark로 패킷을 검사하면 이상하게 ping request 항목은 사라지고 모두 ip fragmentation 으로 인식되던군요.
4일째 밤마다 구글링을 하고 찾아도 구현 방법은 않나오더라고요..
어떻게 설정 혹은 구현을 해야 icmp+ip 헤더에 나머지 ip fragmentation이 딸려가게 할수 있나요??
/* 제가 생각한 방법은 buffer에는 ip+icmp 헤더를 넣어서 전송하고 그전에 nbuffer에 ip헤더(fragmentaion)을 전송하는 방법입니다. 코드에 나왔있지만 offset은 제대로 맞춘상태고 wireshark로 보았을때 의도한대로 나오네요. 그냥 buffer와 nbuffer는 배열로 선언했습니다,, request도 가지 않는 상황이기에 recvfrom 은 구현해 놓지 않았습니다 제 허접한 코드입니다*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/ip.h> #include <errno.h> #include <unistd.h> #include <netinet/ip_icmp.h> unsigned short in_cksum(unsigned short *,int len); int main(int argc,char **argv){ if(argc!=3){ printf("USAGE %s [dest IP] [source ip]\n",argv[0]); exit(1); } int nsock,clnt_size,size; int on=1,i=0,len; char buffer[1480]; struct ip *iphdr; struct in_addr ex_addr; struct icmp *icmp; struct sockaddr_in serv_sock; char nbuffer[1480]; nsock=socket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if(nsock<0){ printf("socket connect error\n"); exit(1); } setsockopt(nsock, IPPROTO_IP, IP_HDRINCL, (char *)&on, sizeof(on) ); bzero(&serv_sock,sizeof(serv_sock)); serv_sock.sin_family=AF_INET; serv_sock.sin_addr.s_addr=inet_addr(argv[1]); //nbuffer 시작 memset(nbuffer,0x0,1480); iphdr=(struct ip*)(nbuffer); iphdr->ip_v=4; iphdr->ip_hl=5; iphdr->ip_p=IPPROTO_ICMP;//IPPROTO_TCP; iphdr->ip_len=htons(1480); iphdr->ip_id=20; iphdr->ip_ttl=125; iphdr->ip_off=htons(IP_MF); iphdr->ip_sum=0; iphdr->ip_tos=0x000; ex_addr.s_addr=inet_addr(argv[2]); iphdr->ip_src=ex_addr; ex_addr.s_addr=inet_addr(argv[1]); iphdr->ip_dst=ex_addr; iphdr->ip_sum=in_cksum((unsigned short *)iphdr,sizeof(struct iphdr)); //ip header end //nbuffer 끝 //buffer 시작 iphdr=(struct ip*)(buffer); iphdr->ip_v=4; iphdr->ip_hl=5; iphdr->ip_p=IPPROTO_ICMP;//IPPROTO_TCP; iphdr->ip_len=htons(1480); iphdr->ip_id=20; iphdr->ip_ttl=125; iphdr->ip_off=htons(185); iphdr->ip_sum=0; iphdr->ip_tos=0x000; ex_addr.s_addr=inet_addr(argv[2]); iphdr->ip_src=ex_addr; ex_addr.s_addr=inet_addr(argv[1]); iphdr->ip_dst=ex_addr; iphdr->ip_sum=in_cksum((unsigned short *)iphdr,sizeof(struct iphdr)); //ip header end icmp=(struct icmp*)(buffer+sizeof(struct ip)); icmp->icmp_type=ICMP_ECHO;//ICMP_UNREACH; icmp->icmp_code=0; icmp->icmp_cksum=0; icmp->icmp_seq=15; icmp->icmp_id=20; icmp->icmp_cksum=in_cksum((unsigned short*)icmp,900); //buffer 끝 sendto(nsock,nbuffer,sizeof(nbuffer),0x0,(struct sockaddr*)&serv_sock,sizeof(serv_sock)); sendto(nsock,buffer,sizeof(buffer),0x0,(struct sockaddr*)&serv_sock,sizeof(serv_sock)); } unsigned short in_cksum(unsigned short *addr,int len) { register int sum = 0; u_short answer = 0; register u_short *w = addr; register int nleft = len; /* * Our algorithm is simple, using a 32 bit accumulator (sum), we add * sequential 16 bit words to it, and at the end, fold back all the * carry bits from the top 16 bits into the lower 16 bits. */ while(nleft > 1) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if(nleft == 1) { *(u_char *)(&answer) = *(u_char *)w ; sum += answer; } /* add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return(answer); }
Forums:
socket() 세번째
socket() 세번째 파라미터 값에 IPPROTO_ICMP 대신 IPPROTO_RAW 또는 255로 설정해 보세요.
그래야만 IP헤더부터 윗단에 패킷을 넣으실 수 있을겁니다.
댓글 달기