Protocol

icmp

불량껌 2010. 6. 3. 11:26

internet control message protocol의 줄임말로 다른 호스트나 게이트웨이에 연결된 네트워크 상태를 알아보는데 사용된다. icmp의 대표적인 프로그램으로 ping이 있다.

icmp는 ip header를 이용한다. ip header의 protocol 1이 icmp이다.
ip header의 protocol을 보면 1이 icmp임을 알 수 있다.

0 HOPOPT, IPv6 Hop-by-Hop Options RFC 1883
1 ICMP, Internet Control Message Protocol RFC 792
2 IGAP, IGMP, RGMP
3 GGP, Gateway to Gateway Protocol
4 IP in IP encapsulation
5 ST, Internet Stream Protocol
6 TCP, Transmission Control Protocol
7 UCL, CBT
8 EGP, Exteriro Gateway Protocol
9 IGRP, Interior Gateway Routing Protocon
10 BBN RCC Monitoring
11 NVP, Network Voice Protocol
12 PUP
13 ARGUS
14 EMCON, Emission Control Protocol
15 XNET, Cross Net Debugger
16 Chaos
17 UDP, User Datagram Protocol
41 IPv6 over IPv4
50 ESP, Encapulating Security Payload
132 SCTP, Stream Control Transmission Protocol

icmp packet 구조는 다음과 같다
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |     Type      |     Code      |          Checksum             |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |           Identifier          |        Sequence Number        |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |     Data ...
 +-+-+-+-+-

icmp header의 type을 보면 다음과 같다.

0 icmp echo replay icmp 요청에 대한 icmp 응답
3 Destination Unreachable Message 수신지까지 메시지가 도착할수 없음
4 Source Quench Message 송신지 억제
5 Redirect Message 재지시
8 icmp echo request 목적지 호스트에 ICMP 응답을 요청한다
11 Time Exceeded Message 데이타그램 시간초과(TTL 초과)
12 Parameter Problem Message 데이타그램에서의 파라메타 문제
13,14 Timestamp or Timestamp Reply Message 13:시간기록요청, 14:시간기록응답

icmp programing
쉽다 빨간 글씨는 필요없는 부분이다.(나만 보기위해 적은 부분)

icmp, sockaddr_in 구조체를 정의해서 내용만 채워 넣고 보내고 받으면 된다.
int icmp_sock; //소켓
struct icmp *p, *rp; //icmp 구조체
struct sockaddr_in addr, from; //sockaddr 구조체
char buffer[1024]; //사용될 버퍼
struct ip *ip;

icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); icmp유형의 소켓을 생성

p = (struct icmp *) buffer;
p->icmp_type = 8; //icmp응답을 요청해야한다.
p->icmp_code=0; //icmp code 0
p->icmp_cksum=0; 
p->icmp_seq=15;
p->icmp_id=1234;
cksum, seq, id 에 적당한 값을 넣어준다.

addr.sin_addr.s_addr = inet_addr(ipaddr); //목적지 주소 입력
addr.sin_family = AF_INET;

//setsockopt(icmp_socket, SOL_SOCKET, SO_BINDTODEVICE, IFName, strlen(IFName)+1);
//이 부분은 소켓 옵션으로 ping에서 -I 옵션처럼 interface device를 선택하는 부분이다. IFName은 device의 이름이다. lo, eth0, lan등의 명을 쓰면 된다. 그럼 선택한 device에서 오는 응답만을 받는다.

sendto(icmp_socket, p, sizeof(*p), MSG_DONTWAIT, (struct sockaddr *)&addr, sizeof(addr));
//icmp packet 전송.

recvfrom(icmp_socket,buffer, 1024, 0, (struct sockaddr *)&from, sizeof(from));
//받으면 된다.

/*실제 원하는 패킷을 받기위해 수정한 부분.. 필요없는 부분이다.
while(1)
{
     tv.tv_sec=2; //2초의 대기시간 설정
     tv.tv_usec = 0;
     setsockopt(icmp_socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); //socket옵션으로 대기시간 동안 응답을 기다림
     ret = recvfrom(icmp_socket,buffer, 1024, 0, (struct sockaddr *)&from, &sl); //icmp packet 수신
     if (ret < 0)
     {
       break;
     }
     ip = (struct ip *)buffer;
     hlen = ip->ip_hl*4;
     rp = (struct icmp *)(buffer+hlen);

//수신받은 packet의 주소가 맞는지 확인
     if((from.sin_addr.s_addr==inet_addr(IPAddr))||(from.sin_addr.s_addr==201369792)) 
     {
       if(rp->icmp_type != 8) //echo request packet이 아닌지 확인
       {
        break;
       }
     }
}*/


ip = (struct ip *)buffer; //ip패킷이므로..
hlen = ip->ip_hl*4; //header length 저장
rp = (struct icmp *)(buffer+hlen); //buffer의 header length뒤 부터 icmp 저장

//rp값을 확인 후 종료

close(icmp_socket);