랜달프 2008. 4. 6. 16:18

http://www.winpcap.org/docs/docs_40_2/html/group__wpcap__tut3.html

 

참고로 아래는 공부하려고 정리한 것을 올려놨기 때문에 많은 부분이 틀렸을수도있다.

아직 내가 이쪽의 전문가도 아니고 공부하는 입장이기 때문에 혹 참조하시는 분들은 참조만할뿐 맹목적으로 믿지는 않았으면 좋겠다. 직접코드를 쳐보고 구현해보자.

 

Opening an adapter and capturing the packets

adapter를 열고 그리고 패킷 캡쳐하기

Now that we've seen how to obtain an adapter to play with, let's start the real job, opening an adapter and capturing some traffic. In this lesson we'll write a program that prints some information about each packet flowing through the adapter.

The function that opens a capture device is pcap_open(). The parameters, snaplen, flags and to_ms deserve some explanation.

 

지금까지 우리는 작동하는 adapter를 얻는 방법에 대해 알아 보았다. 이제 실제 adapter을 열고 그리고 약간의 트래픽을 캡쳐하는 작업을 시작해보자.

이번 장에서는 우리는 adapter를 따라 흐르는 각각의 패킷에 대한 몇몇 정보를 출력해주는 프로그램에 대해서 기술할 것이다.

capture device를 여는 함수는 pcap_open()함수이다. 이함수의 파라미터 snaplen, flags and to_ms 는 약간의 설명을 할 필요가 있다.

 

* 참고

pcap_t* pcap_open ( const char * source,

int snaplen,

int flags,

int read_timeout,

struct pcap_rmtauth * auth,

char * errbuf

)

 

snaplen specifies the portion of the packet to capture. On some OSes (like xBSD and Win32), the packet driver can be configured to capture only the initial part of any packet: this decreases the amount of data to copy to the application and therefore improves the efficiency of the capture. In this case we use the value 65536 which is higher than the greatest MTU that we could encounter. In this manner we ensure that the application will always receive the whole packet.

 

snaplen 는 캡쳐하기위한 패킷의 비율(몫)을 명세하고 있다. OSes(xBSD and Win32와 같이)상에서, packet driver는 단지 어떤 패킷의 처음 부분만을 캡쳐하기 위해 구성되어질수 있다.

즉 packet driver는 application로부터 데이터를 복사하는 양을 줄인다. 그리고 그러한 까닭에 캡쳐의 효율성은 개선된다. 이러한 경우 우리가 직면할수 있는 가장 큰 MTU의 값보다 큰 65536 값을 사용한다. 말하자면 우리는 그 application은 항상 모든(전체)패킷을 받을수있다는 것을 보장한다.

 

* 패킷에 도착해서 그 패킷을 담을 버퍼의 크기를 정하는 것은 snaplen 변수인데 만약 너무작게하면 패킷의 일부분만을(즉 패킷의 처음부부만) 버퍼에 담게 되어서 나머지 부분은 담을 수없게된다. 그래서 이런 현상을 막기위해 MTU 즉 최대전송단위의 값보다 큰 65536의 값을 설정하게 해주면 application은 패킷 손실없이 모든 패킷을 받을 수있다는 말이다.

 

* 참고

MTU (Maximum Transmission Unit) ; 최대 전송 단위

 

flags: the most important flag is the one that indicates if the adapter will be put in promiscuous mode. In normal operation, an adapter only captures packets from the network that are destined to it; the packets exchanged by other hosts are therefore ignored. Instead, when the adapter is in promiscuous mode it captures all packets whether they are destined to it or not. This means that on shared media (like non-switched Ethernet), WinPcap will be able to capture the packets of other hosts. Promiscuous mode is the default for most capture applications, so we enable it in the following example.

 

이거 이해 안돼서 꽤걸림~~ 맞는건지 정확한지는 모르겠음 실험을 안해봐서 ㅋ ㅋ ㅋ

 

플래그: 가장 중요한 플래그는 adapter가 promiscuous mode 설정되어있는지 아닌지 보여주는 것이다. 보통의 경우 단지 adapter는 adapter로 예정되어 있는 패킷을 네트워크로부터 캡쳐한다. 즉 다른 호스트에서 교환되어지는 패킷은 그런 까닭에 무시된다. 대신에 adapter가 promiscuous mode있을 때에는 adapter는 패킷이 자신에게 오는 패킷이던지 혹은 그렇지 않던간에 모든 패킷을 캡쳐한다.(좀 의역했음)

이것은 shared media (like non-switched Ethernet)에서 winpcap은 다른 호스트에 패킷도 캡쳐할수 있다. Promiscuous mode는 대부분의 캡쳐 어플리케이션에서 디폴트이다. 그래서 우리는 아래에 예제에서 그것을 실행했다.

 

* 추가 설명

A ------ B -----C

만약 B에서 패킷캡쳐를 한다고 가정했을 때 일반 캡쳐는 A가 C로 패킷을 보낸 경우 자신의 네트워크를 따라서 이동하지만 자신의 adapter로 오는 패킷이 아니기 때문에 패킷캡쳐를 실행하지 않는다. 하지만 그렇지 않는 경우 즉 promiscuous mode로 설정되어있는 경우에는 자신을 걸치는 모든 패킷을 캡쳐한다는 내용이다. (제생각은 이런데 님생각은?)

 

 

to_ms specifies the read timeout, in milliseconds. A read on the adapter (for example, with pcap_dispatch() or pcap_next_ex()) will always return after to_ms milliseconds, even if no packets are available from the network. to_ms also defines the interval between statistical reports if the adapter is in statistical mode (see the lesson "\ref wpcap_tut9" for information about statistical mode). Setting to_ms to 0 means no timeout, a read on the adapter never returns if no packets arrive. A -1 timeout on the other side causes a read on the adapter to always return immediately.

 

to_ms 는 read timeout(밀리세컨드)를 명시한다. 설령 네트워크로부터 사용할수 있는 패킷이 존재 하지 않을때에도 pcap_dispatch() or pcap_next_ex() 함수로 adapter를 읽을 때에는 항상 to_ms milliseconds, 후에 리턴한다. to_ms는 또한 만약 adapter가 statistical mode에 있다면 statical report 사이의 간격을 정의한다.

("\ref wpcap_tut9" lesson 편에 statistical mode에 관한 정보를 볼 수 있다.)

to_ms를 0으로 세팅한다는 의미는 timeout이 없다는 의미이다. 다시 말하면 만약 패킷이 도착하지 않았다면 adapter를 읽은것에 대해서 결코 반환하지 않겠다라는 것을 의미한다.

또 다른경우에 timeout를 -1로 세팅하는 경우에는 adapter의 읽기를 항상 바로 반환한다는 걸 뜻한다.

 

* 내생각

statistical mode로 설정하면 트래픽을 정보를 보고받게 되는데 이때의 to_ms는 트래픽의 통계 보고(statical report)의 간격을 정할 수 있다라는 의미인것같다. 만약 1000으로 하면 1초마다 통계보고를 얻을 수 있다는 정도로 생각할 수 있다.

adapater에서 패킷을 읽어 들어올 때 만약 to_ms를 0으로 설정하면 만약 패킷이 들어오지 않는다면 계속 대기 상태로 있을 것이고 만약 -1로 세팅한다면 패킷이 들어오는 즉시 반환한다는 의미인 것 같다. 만약 1000설정하면 1초를 기다린다.

왜냐하면 밀리세컨드 10-3 * 1000 =1 초 이기 때문이다.

 

 

Once the adapter is opened, the capture can be started with pcap_dispatch() or pcap_loop(). These two functions are very similar, the difference is that pcap_ dispatch() returns (although not guaranteed) when the timeout expires while pcap_loop() doesn't return until cnt packets have been captured, so it can block for an arbitrary period on an under-utilized network. pcap_loop() is enough for the purpose of this sample, while pcap_dispatch() is normally used in a more complex program.

 

일단 adapter 열리게 되면 패킷 캡쳐가 pcap_dispatch() or pcap_loop(). 두함수와 함께 시작될수 있다. 이 두함수의 매우 유사하다. 차이점은 pcap_ dispatch()함수는 timeout가 끝났을 때(만료되었을 때) 리턴한다.(비록 보장할 수는 없다.) 하지만 pcap_loop()함수는 cnt packets이 캡쳐가 되지 않았을 때까지 리턴하지 않는다. 그래서 이 함수는 under-utilized network 상에서 임의의 기간 동안 블락될 수도 있다.

pcap_loop()함수는 이 샘플의 목적에 충분하다. 반대에 pcap_dispatch()는 일반적으로 좀더 복잡한 프로그램에서 사용되어진다.

 

* 참고

int pcap_dispatch ( pcap_t * p,

int cnt,

pcap_handler callback,

u_char * user

)

 

int pcap_loop ( pcap_t * p,

int cnt,

pcap_handler callback,

u_char * user

)

 

-> 내생각 pcap_open() 함수를 호출해서 adapter을 열고 다음에 pcap_dispatch() or pcap_loop() 둘중하나를 호출하게 되면 패킷캡쳐가 가능하다는 말이다. pcap_loop 함수의 경우 cnt의 값만큼 패킷을 얻지 못하면 리턴하지 못하는것이고 pcap_ dispatch함수는 타임아웃이 걸리때까지 대기한다는 것이다.

 

Both of these functions have a callback parameter, packet_handler, pointing to a function that will receive the packets. This function is invoked by libpcap for every new packet coming from the network and receives a generic status (corresponding to the user parameter of pcap_loop() and pcap_dispatch()), a header with some information on the packet like the timestamp and the length and the actual data of the packet including all the protocol headers. Note that the frame CRC is normally not present, because it is removed by the network adapter after frame validation. Note also that most adapters discard packets with wrong CRCs, therefore WinPcap is normally not able to capture them.

 

이 두함수 pcap_ dispatch, pcap_loop는 callback 파라미터(패킷을 받을 수 있는 함수를 가리키고있는 packet_handler () )를 가지고 있다. 이 함수는(packet_handler() )는 매번 새로운 패킷이 네트워크로부터 도착하게 되면 libcap에 의해서 깨어지고 그리고 pcap_loop() and pcap_dispatch() 함수의 유저 파라미터와 상응되는 일반적인 상태를 얻는다. 일반적인 상태란 모든 프로토콜헤더를 포함하는 패킷의 timestamp 그리고 길이 그리고 실제 데이터와 같은 패킷의 정보를 가지고 있는 헤더를 말한다. 일반적으로 CRC 존재하지 않는다는 것을 주목해라. 왜냐하면 그것은 frame validation로부터 네트워크 어댑터에 의해서 제거되기 때문이다. 또한 대부분의 어댑터는 잘못된 CRC를 가지고 있는 패킷을 버린다는 것을 주목해라. 그러므로 winpcap는 보통 그것들을 캡쳐 할 수 없다.

* 참고

void packet_handler(u_char *param, const struct pcap_pkthdr *header, const u_char *pkt_data)

 

struct pcap_pkthdr

 

timeval ts // time stamp

bpf_u_int32 caplen // length of portion present

bpf_u_int32 len // length this packet (off wire)

* 내생각

pcap_loop함수의 callback 인자(세번째 파라미터) 즉 packet_handler함수는 네트워크카드, 즉 어댑터에 패킷이 도착하게 되면 libcap 에 의해서 일반적인 정보를 받을 것이다. 그중 CRC (오류 체크하는 용도임, 자세한건 찾아 보세요)가 존재하지 않는 이유는 CRC의 유효성을 네트워크 어댑터가 검사하는데 만약 유효하다면 네트워크 단에서 이부분을 제거하기 때문에 우리가 이것을 확인할 수가 없고 만약 문제가 있다면 네트워크 어댑터에서 문제가 있는 패킷을 버리기 때문에 우리는 CRC의 존재를 확인할 수가 없다.

 

 

The above example extracts the timestamp and the length of every packet from the pcap_pkthdr header and prints them on the screen.

 

위에 예제는 pcap_pkthdr header의 모든 패킷길이와 timestamp를 추출했다. 그리고 그것을 화면에 출력해준다.

 

Please note that there may be a drawback using pcap_loop() mainly related to the fact that the handler is called by the packet capture driver; therefore the user application does not have direct control over it. Another approach (and to have more readable programs) is to use the pcap_next_ex() function, which is presented in the next example (Capturing the packets without the callback).

 

여기에는 패킷캡쳐 드라이버에 의해서 호출된 핸들러와 많은 관련이 있는 pcap_loop() 함수를 사용함으로써 결점이 있을 수 있다는 것에 주목하라, 그러므로 유저 applicationdms 그것을 직접적으로 컨트롤할 수 없다. 또 다른 접근방법( 좀더 가독성이 좋은 프로그램)은 pcap_next_ex()함수를 사용하는 것이다. 이 함수는 다음번에 예제(callback없이 패킷을 캡쳐할 수 있는 예제)에서 볼 수 있다.

[출처] winpcap 3장|작성자 fox3831