현재 소켓을 이용해서 traceroute와 비슷한 프로그램을 코딩 중입니다. 여기서 제가 IP header option을 사용해야 하는데요, 정확한 방법을 모르겠습니다.
자료로 나와 있는 것도 없구 말이죠. IP header option을 사용해 보신 분 계시면 답변 부탁드립니다. 물론 예제 source file이라도 있으시면... 정말 눈물겹도록 감사하겠죠... 그럼, 이만...
Seq만 검사하는 ping 만들었던거 소스 올립니다. 참고가 될지요... 참고로 RAW socket이므로 "root" 권한에서 실행되어야 함은 당연지사로 생각하시면 되고요.
이거 코드 잘못 수정하면 네트웍 이상해지는 경우도 있을수 있으니까 Local에서만 테스트해보심을 권고 합니다.
/* Copyright (c) Information Equipment co.,LTD. Code by JaeHyuk Cho <mailto:minzkn@infoeq.co.kr> - Simple is best ! (Sequence number check ping) */ #include <stdio.h> #include <string.h> #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h> #include <netinet/ip_icmp.h> #include <arpa/inet.h> #include <netdb.h> #include <unistd.h> static int __MZ_ICMP_CheckSum__(void *s_Buffer, int s_Size) { int s_Return = 0; if(s_Size & 1)s_Return += (int)((*(unsigned char *)s_Buffer)++); s_Size >>= 1; while(s_Size-- > 0)s_Return += (int)(*(((unsigned short *)s_Buffer)++)); if(s_Size == 1)s_Return += (int)(*(unsigned char *)(s_Buffer)); s_Return = (s_Return >> 16) + (s_Return & 0xFFFF); s_Return += (s_Return >> 16); return((~s_Return) & 0xffff); } int CORE_Ping(const char *s_HostName, unsigned int s_Index, unsigned int s_TimeOut) { int s_Return = (-1), s_Socket, s_SendBytes, s_RecvBytes, s_IsSelect; struct protoent *s_ProtoEntry; struct hostent *s_HostEntry; struct sockaddr_in s_PingAddress, s_FromAddress; socklen_t s_FromAddressLength; struct icmp *s_ICMP; struct iphdr *s_IPHeader; unsigned char s_ICMP_Packet[ 60 + 76 + 56 ]; /* Packet assembly */ fd_set s_FD; struct timeval s_TimeVal; s_HostEntry = gethostbyname(s_HostName); if(s_HostEntry) { memset((void *)(&s_PingAddress), 0, sizeof(s_PingAddress)); s_PingAddress.sin_family = AF_INET; memcpy((void *)(&s_PingAddress.sin_addr), s_HostEntry->h_addr, sizeof(s_PingAddress.sin_addr)); memset((void *)(&s_ICMP_Packet[0]), 0, sizeof(s_ICMP_Packet)); s_ICMP = (struct icmp *)(&s_ICMP_Packet[0]); s_ICMP->icmp_type = ICMP_ECHO; s_ICMP->icmp_seq = s_Index; s_ICMP->icmp_id = getpid() & 0xffff; gettimeofday((struct timeval *)(&s_ICMP_Packet[8]), (void *)0); s_ICMP->icmp_cksum = __MZ_ICMP_CheckSum__((void *)(&s_ICMP_Packet[0]), sizeof(s_ICMP_Packet)); s_ProtoEntry = getprotobyname("icmp"); s_Socket = socket(AF_INET, SOCK_RAW, s_ProtoEntry ? s_ProtoEntry->p_proto : 1); setuid(getuid()); /* Who are you ? */ if(s_Socket >= 0) { s_SendBytes = sendto(s_Socket, (void *)(&s_ICMP_Packet[0]), sizeof(s_ICMP_Packet), MSG_NOSIGNAL, /* Ignore broken pipe */ (struct sockaddr *)(&s_PingAddress), sizeof(s_PingAddress)); if(s_SendBytes == sizeof(s_ICMP_Packet)) { memset((void *)(&s_FromAddress), 0, sizeof(s_FromAddress)); s_FromAddressLength = sizeof(s_FromAddress); memset((void *)(&s_ICMP_Packet[0]), 0, sizeof(s_ICMP_Packet)); s_TimeVal.tv_sec = s_TimeOut, s_TimeVal.tv_usec = 0; FD_ZERO(&s_FD); FD_SET(s_Socket, &s_FD); s_IsSelect = select(s_Socket + 1, &s_FD, (fd_set *)0, (fd_set *)0, &s_TimeVal); if(s_IsSelect > 0 && FD_ISSET(s_Socket, &s_FD) != 0) { s_RecvBytes = recvfrom(s_Socket, (void *)(&s_ICMP_Packet[0]), sizeof(s_ICMP_Packet), MSG_NOSIGNAL, /* Ignore broken pipe */ (struct sockaddr *)(&s_FromAddress), (socklen_t *)(&s_FromAddressLength)); } else s_RecvBytes = 0; if(s_RecvBytes >= 76) { s_IPHeader = (struct iphdr *)(&s_ICMP_Packet[0]); s_ICMP = (struct icmp *)(&s_ICMP_Packet[ s_IPHeader->ihl << 2 ]); if(s_ICMP->icmp_type == ICMP_ECHOREPLY) { /* TODO: Packet check sum need Time compute Duplicate packet check Send packet & Recv packet -> Two thread or alarm */ s_Return = (int)s_ICMP->icmp_seq; } } } close(s_Socket); } } return(s_Return); } int main(int s_Argc, char *s_Argv[]) { int s_Return, s_Check, s_Index, s_ErrorCount, s_IsError, s_Count; fprintf(stdout, "MZ_Ping v0.0.1 - Code by JaeHyuk Cho <minzkn@infoeq.co.kr>\n\n"); if(s_Argc > 1) { s_ErrorCount = 0, s_Index = 1; if(s_Argc > 2)sscanf(s_Argv[2], "%i", &s_Count); else s_Count = 8; do { s_Check = CORE_Ping(s_Argv[1], s_Index /* Request sequence number */, 4u /* Timeout 4 second */); if(s_Check != s_Index)s_ErrorCount++, s_IsError = 1; else s_IsError = 0; fprintf(stdout, "Ping[%s]: %s (Seq %d->%d) - ERR=%d\n", s_Argv[1], s_IsError == 0 ? "OK" : "LOSS", s_Index, s_Check, s_ErrorCount); usleep(10000); }while(s_Index++ < s_Count); fprintf(stdout, "Total %d%% loss.\n", s_ErrorCount * 100 / s_Index); s_Return = s_ErrorCount; } else { fprintf(stdout, "usage: ping <host> <count>\n"); s_Return = 0; } return(s_Return); } /* End of source */
텍스트 포맷에 대한 자세한 정보
<code>
<blockcode>
<apache>
<applescript>
<autoconf>
<awk>
<bash>
<c>
<cpp>
<css>
<diff>
<drupal5>
<drupal6>
<gdb>
<html>
<html5>
<java>
<javascript>
<ldif>
<lua>
<make>
<mysql>
<perl>
<perl6>
<php>
<pgsql>
<proftpd>
<python>
<reg>
<spec>
<ruby>
<foo>
[foo]
Seq만 검사하는 ping 만들었던거 소스 올립니다.참고가 될지요..
Seq만 검사하는 ping 만들었던거 소스 올립니다.
참고가 될지요... 참고로 RAW socket이므로 "root" 권한에서
실행되어야 함은 당연지사로 생각하시면 되고요.
이거 코드 잘못 수정하면 네트웍 이상해지는 경우도 있을수 있으니까
Local에서만 테스트해보심을 권고 합니다.
댓글 달기