ping (ICMP/RAW socket) 예제

Programming/Network 2007/05/09 11:48 장인정신
span class=postbody완전한 ping 은 아닙니다. 정말로 최소구현입니다. br / br / 이것은 sid 가 걸려있거나 root 유저에서 실행가능합니다. 이유는 RAW socket 이기 때문입니다. br / br / /spantable align=center border=0 cellpadding=3 cellspacing=1 width=90%tbodytr tdspan class=genmedb코드:/b/span/td /tr tr td class=code/* br / Copyright (c) Information Equipment co.,LTD. br / Code by JaeHyuk Cho lt;mailto:minzkn@infoeq.co.krgt; br / br / - Simple is best !nbsp; nbsp;(Sequence number check ping) br / br / Bugreport : To JaeHyuk Cho br / */ br / br / #include lt;stdio.hgt; br / #include lt;string.hgt; br / #include lt;sys/types.hgt; br / #include lt;sys/param.hgt; br / #include lt;sys/time.hgt; br / #include lt;sys/socket.hgt; br / #include lt;netinet/in.hgt; br / #include lt;netinet/ip.hgt; br / #include lt;netinet/ip_icmp.hgt; br / #include lt;arpa/inet.hgt; br / #include lt;netdb.hgt; br / #include lt;unistd.hgt; br / br / static int __MZ_ICMP_CheckSum__(void *s_Buffer, int s_Size) br / { br / int s_Return = 0; br / if(s_Size amp; 1)s_Return += (int)((*(unsigned char *)s_Buffer)++); br / s_Size gt;gt;= 1; br / while(s_Size-- gt; 0)s_Return += (int)(*(((unsigned short *)s_Buffer)++)); br / if(s_Size == 1)s_Return += (int)(*(unsigned char *)(s_Buffer)); br / s_Returnnbsp; = (s_Return gt;gt; 16) + (s_Return amp; 0xFFFF); br / s_Return += (s_Return gt;gt; 16); br / return((~s_Return) amp; 0xffff); br / } br / br / int CORE_Ping(const char *s_HostName, unsigned int s_Index, unsigned int s_TimeOut) br / { br / intnbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp;s_Return = (-1), s_Socket, s_SendBytes, s_RecvBytes, s_IsSelect; br / struct protoentnbsp; nbsp; *s_ProtoEntry; br / struct hostentnbsp; nbsp; nbsp;*s_HostEntry; br / struct sockaddr_innbsp; s_PingAddress, s_FromAddress; br / socklen_tnbsp; nbsp; nbsp; nbsp; nbsp; nbsp;s_FromAddressLength; br / struct icmpnbsp; nbsp; nbsp; nbsp; *s_ICMP; br / struct iphdrnbsp; nbsp; nbsp; nbsp;*s_IPHeader; br / unsigned charnbsp; nbsp; nbsp; nbsp;s_ICMP_Packet[ 60 + 76 + 56 ]; /* Packet assembly */ br / fd_setnbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; s_FD; br / struct timevalnbsp; nbsp; nbsp; s_TimeVal; br / s_HostEntry = gethostbyname(s_HostName); br / if(s_HostEntry) br / { br / nbsp; memset((void *)(amp;s_PingAddress), 0, sizeof(s_PingAddress)); br / nbsp; s_PingAddress.sin_family = AF_INET; br / nbsp; memcpy((void *)(amp;s_PingAddress.sin_addr), s_HostEntry-gt;h_addr, sizeof(s_PingAddress.sin_addr)); br / nbsp; memset((void *)(amp;s_ICMP_Packet[0]), 0, sizeof(s_ICMP_Packet)); br / nbsp; s_ICMP = (struct icmp *)(amp;s_ICMP_Packet[0]); br / nbsp; s_ICMP-gt;icmp_typenbsp; = ICMP_ECHO; br / nbsp; s_ICMP-gt;icmp_seqnbsp; nbsp;= s_Index; br / nbsp; s_ICMP-gt;icmp_idnbsp; nbsp; = getpid() amp; 0xffff; br / nbsp; gettimeofday((struct timeval *)(amp;s_ICMP_Packet[8]), (void *)0); br / nbsp; s_ICMP-gt;icmp_cksum = __MZ_ICMP_CheckSum__((void *)(amp;s_ICMP_Packet[0]), sizeof(s_ICMP_Packet)); br / nbsp; s_ProtoEntry = getprotobyname(icmp); br / nbsp; s_Socket = socket(AF_INET, SOCK_RAW, s_ProtoEntry ? s_ProtoEntry-gt;p_proto : 1); br / nbsp; setuid(getuid()); /* Who are you ? */ br / nbsp; if(s_Socket gt;= 0) br / nbsp; { br / nbsp; nbsp;s_SendBytes = sendto(s_Socket, (void *)(amp;s_ICMP_Packet[0]), sizeof(s_ICMP_Packet), br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; MSG_NOSIGNAL, /* Ignore broken pipe */ br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; (struct sockaddr *)(amp;s_PingAddress), sizeof(s_PingAddress)); br / nbsp; nbsp;if(s_SendBytes == sizeof(s_ICMP_Packet)) br / nbsp; nbsp;{ br / nbsp; nbsp; memset((void *)(amp;s_FromAddress), 0, sizeof(s_FromAddress)); br / nbsp; nbsp; s_FromAddressLength = sizeof(s_FromAddress); br / nbsp; nbsp; memset((void *)(amp;s_ICMP_Packet[0]), 0, sizeof(s_ICMP_Packet)); br / nbsp; nbsp; s_TimeVal.tv_sec = s_TimeOut, s_TimeVal.tv_usec = 0; br / nbsp; nbsp; FD_ZERO(amp;s_FD); FD_SET(s_Socket, amp;s_FD); br / nbsp; nbsp; s_IsSelect = select(s_Socket + 1, amp;s_FD, (fd_set *)0, (fd_set *)0, amp;s_TimeVal); br / nbsp; nbsp; if(s_IsSelect gt; 0 amp;amp; FD_ISSET(s_Socket, amp;s_FD) != 0) br / nbsp; nbsp; { br / nbsp; nbsp; nbsp;s_RecvBytes = recvfrom(s_Socket, (void *)(amp;s_ICMP_Packet[0]), sizeof(s_ICMP_Packet), br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp;MSG_NOSIGNAL, /* Ignore broken pipe */ br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp;(struct sockaddr *)(amp;s_FromAddress), (socklen_t *)(amp;s_FromAddressLength)); br / nbsp; nbsp; } br / nbsp; nbsp; else s_RecvBytes = 0; br / nbsp; nbsp; if(s_RecvBytes gt;= 76) br / nbsp; nbsp; { br / nbsp; nbsp; nbsp;s_IPHeader = (struct iphdr *)(amp;s_ICMP_Packet[0]); br / nbsp; nbsp; nbsp;s_ICMP = (struct icmp *)(amp;s_ICMP_Packet[ s_IPHeader-gt;ihl lt;lt; 2 ]); br / nbsp; nbsp; nbsp;if(s_ICMP-gt;icmp_type == ICMP_ECHOREPLY) br / nbsp; nbsp; nbsp;{ br / nbsp; nbsp; nbsp; /* TODO: br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; Packet check sum need br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; Time compute br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; Duplicate packet check br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; nbsp; Send packet amp; Recv packet -gt; Two thread or alarm br / nbsp; nbsp; nbsp; */ br / nbsp; nbsp; nbsp; s_Return = (int)s_ICMP-gt;icmp_seq; br / nbsp; nbsp; nbsp;} br / nbsp; nbsp; } br / nbsp; nbsp;} br / nbsp; nbsp;close(s_Socket); br / nbsp; } br / } br / return(s_Return); br / } br / br / int main(int s_Argc, char *s_Argv[]) br / { br / int s_Return, s_Check, s_Index, s_ErrorCount, s_IsError, s_Count; br / fprintf(stdout, MZ_Ping v0.0.1 - Code by JaeHyuk Cho lt;minzkn@infoeq.co.krgt;\n\n); br / if(s_Argc gt; 1) br / { br / nbsp; s_ErrorCount = 0, s_Index = 1; br / nbsp; if(s_Argc gt; 2)sscanf(s_Argv[2], %i, amp;s_Count); br / nbsp; else s_Count = 8; br / nbsp; do br / nbsp; { br / nbsp; nbsp;s_Check = CORE_Ping(s_Argv[1], s_Index /* Request sequence number */, 4u /* Timeout 4 second */); br / nbsp; nbsp;if(s_Check != s_Index)s_ErrorCount++, s_IsError = 1; br / nbsp; nbsp;else s_IsError = 0; br / nbsp; nbsp;fprintf(stdout, Ping[%s]: %s (Seq %d-gt;%d) - ERR=%d\n, br / nbsp; nbsp; nbsp; nbsp; nbsp; nbsp;s_Argv[1], s_IsError == 0 ? OK : LOSS, s_Index, s_Check, s_ErrorCount); br / nbsp; nbsp;usleep(10000); br / nbsp; }while(s_Index++ lt; s_Count); br / nbsp; fprintf(stdout, Total %d%% loss.\n, s_ErrorCount * 100 / s_Index); br / nbsp; s_Return = s_ErrorCount; br / } br / else br / { br / nbsp; fprintf(stdout, usage: ping lt;hostgt; lt;countgt;\n); br / nbsp; s_Return = 0; br / } br / return(s_Return); br / } br / br / /* End of source *//td/tr/tbody/table
크리에이티브 커먼즈 라이센스
Creative Commons License
2007/05/09 11:48 2007/05/09 11:48
받은 트랙백이 없고, 댓글 2개가 달렸습니다.

댓글+트랙백 RSS :: http://blog.minzkn.com/rss/response/106

댓글+트랙백 ATOM :: http://blog.minzkn.com/atom/response/106

트랙백 주소 :: http://blog.minzkn.com/trackback/106

트랙백 RSS :: http://blog.minzkn.com/rss/trackback/106

트랙백 ATOM :: http://blog.minzkn.com/atom/trackback/106

댓글을 달아 주세요

댓글 RSS 주소 : http://blog.minzkn.com/rss/comment/106
댓글 ATOM 주소 : http://blog.minzkn.com/atom/comment/106
  1. 김재석 2007/06/06 22:17  댓글주소  수정/삭제  댓글쓰기

    유용한 소스 잘 참조했습니다.
    그런데 Ping 손실률 구하는 라인의 코딩이 조금 잘못 된 것 같습니다.
    fprintf(stdout, Total %d%% loss.\n, s_ErrorCount * 100 / s_Index);

    :s_Index를 s_Count로 바꿔야 맞을 것 같네요.

  2. 2008/04/23 20:38  댓글주소  수정/삭제  댓글쓰기

    잘 썻음니다..