[질문] libpcap을 이용한 패킷캡쳐중 인터페이스가 다운될경우 문제
글쓴이: ecstasy5001 / 작성시간: 월, 2008/01/14 - 1:18오후
libpcap을 이용해서 패킷을 캡쳐하는 프로그램을 만들고 있는데
물리적인 인터페이스나 논리적인 인터페이스(ipsec0 같은)가 다운될경우
프로그램이 종료되게 할라고 하는데 이게 잘 안됩니다.
pcap_open_live 함수를 이용해서 타임아웃을 지정하고
pcap_loop, pcap_detatch, pcap_next 등 여러가지 함수를 사용해봤지만
모든함수 전부다 인터페이스가 다운되면 타임아웃이 무시된채 무한 대기상태가 되었습니다.
인터페이스가 다운되었을때 이것을 확인할수 있는방법이 있는지 궁금합니다.
Forums:


아래는 제가 예전에
아래는 제가 예전에 브릿지 방화벽에 사용하려고 만든 테스트용 소스입니다.
아래의 소스는 상단 백본 스위치나 하단 백본 스위치의 오류로 인해 스위치쪽 포트의 링크가 다운이 되었을 경우 방화벽에서 bypass 를 하기 위해 작성했었습니다.
브릿지 방화벽이 스위치 사이에 들어가니 상단이나 하단 스위치 하나가 죽었음에도 불구하고 계속 트래픽이 흘러 트래픽이 유실이 되더라구요 ㅡ.ㅡ;;;
단순하게 NIC 의 LINK 상태만 감지하여 출력해 주는 프로그램인데 요걸 응용하면 아마 원하시는 기능을 간단하게 나마 만드실 수 있을거라 봅니다.
저도 ethtool 이나 mii-tool 을 보고 만든거라 허접합니다.
더 깊게 보고 싶으시면 ethtool 이나 mii-tool 소스를 보시는게 나을 겁니다.
그리고.. 물리적인 eth2(in), eth3(out) 를 브릿지로 묶은 br0 도 측정이 되었으니 아마 논리 인터페이스도 제대로 검출하지 않을까 합니다.
단, 아래의 코드는 물리적인 인터페이스가 죽으면 해당 인터페이스는 인식을 하지 못합니다.
즉, "ip link show" 나 ethtool 로 보았을때 물리적 인터페이스가 인식은 되었지만, ifconfig 에 나타나지 않는 경우에는 정상적으로 출력을 하지 않습니다.
제가 테스트한 모든 리눅스 서버에서는 정상적으로 되었었는데 글쎄요.. 안될지도 모르겠네요.
커널단이나 iptables 단에서는 패킷 캡쳐를 해봤는데.. libpcap 은 써보질 않아서 약간 엉뚱한 쪽으로 답변을 달게 되네요.
도움이 되었으면 좋겠습니다.
#include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <net/if.h> #include <arpa/inet.h> #include <linux/sockios.h> #define ETHTOOL_GLINK 0x0000000a typedef __uint32_t __u32; struct ethtool_value { __u32 cmd; __u32 data; }; int main (int argc, char **argv) { // 이더넷 데이터 구조체 struct ifreq *ifr; struct sockaddr_in *sin; struct sockaddr *sa; // 이더넷 설정 구조체 struct ifconf ifcfg; struct ethtool_value edata; int fd; int n; int numreqs = 30; fd = socket (AF_INET, SOCK_DGRAM, 0); int link; memset (&ifcfg, 0, sizeof (ifcfg)); ifcfg.ifc_buf = NULL; ifcfg.ifc_len = sizeof (struct ifreq) * numreqs; ifcfg.ifc_buf = malloc (ifcfg.ifc_len); for (;;) { ifcfg.ifc_len = sizeof (struct ifreq) * numreqs; ifcfg.ifc_buf = realloc (ifcfg.ifc_buf, ifcfg.ifc_len); if (ioctl (fd, SIOCGIFCONF, (char *) &ifcfg) < 0) { perror ("SIOCGIFCONF "); exit; } break; } // 네트워크 장치의 정보를 얻어온다. ifr = ifcfg.ifc_req; for (n = 0; n < ifcfg.ifc_len; n += sizeof (struct ifreq)) { // 주소값을 출력하고 링크 상태 확인 sin = (struct sockaddr_in *) &ifr->ifr_addr; printf ("[%s]\n", ifr->ifr_name); printf ("IP %s\n", inet_ntoa (sin->sin_addr)); edata.cmd = ETHTOOL_GLINK; ifr->ifr_data = (caddr_t) & edata; link = ioctl (fd, SIOCETHTOOL, (char *) ifr); printf ("Link : %s\n\n", edata.data ? "connected" : "not connect"); ifr++; } }댓글 달기