IP header option을 사용하는 방법에 대해

hwsong의 이미지

현재 소켓을 이용해서 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 */