NMS using ucd snmp
글쓴이: flatony / 작성시간: 금, 2003/05/02 - 6:29오후
ucd snmp api / command를 이용해서 일정 주기마다
등록된 agent에 폴링해서 MIB값을 가져오는 엔진을 만들생각입니다.
그런데 처음부터 막히네요
제작 환경은 linux 7.3 gcc 3.1.1 이구요 language는 C 로 구현할 거구요
등록된 agent의 ip를 확인한후 ping을 날려서 장비가 살아있는지
죽어있는지 확인한다음에 snmp 명령을 사용해서 MIB값을 가져와야할것같은데
프로그램 내부에서 ping명령을 사용해서 값을 가져온후에 내부에서
time이 3000ms 이상이거나 timeout이면 장비가 죽었다 판단하고
제대로 온다면 살아있다고 판단하게 하려고 하는데
system()함수를 썼더니 컴파일한후 쉘상태에서 실행되더라구요
결과값을 내부에서 받아서 time부분의 결과를 처리해야하는데,,,
음,,,,좀 장황하죠 ^^;;;
암튼,,,,쉘상태에서 쓰이는 프로그램을 제가 만드는 프로그램내에서 실행시킨후
값을 파싱하는 방법이 있는지 궁금합니다...
당최 어떻게 해야하는지 실마리 조차 풀수가 없으니 답답하기 그지없습니다.
고수님들께서 도움을 주시면 감사하겠습니다. ^^
Forums:


외부프로그램을 써야만한다면....1. system 을 쓰지 마
외부프로그램을 써야만한다면....
1.
system 을 쓰지 마시고,
pipe, fork, dup2, exec 순서로 자프로세스의 표준 출력을 pipe로 받아 볼 수 있는 방법.
2.
system 을 쓸 때, 모든 출력을 특정 파일로 redirect 한 뒤 그 file을 읽는 방ㅂ법.
쉬운것으로 하셔요..
3. ping source를 가져다가 쓰는 것도.. 좋은 방법일지도 ..
---
http://coolengineer.com
참고.....
저의 경우에는 router에 ping을 날리고 살아있는 것들에 대해서만 snmp와 cli 명령으로 데이타를 수집하는 프로그램을 개발한 적이 있는데...
(물론 CLI command는 router에 telnet으로 들어가서....)
ping 프로그램을 만들어 썼습니다. 가능하면 만들어 보심이...
ping 프로그램 설명은 stevens 아저씨의 unp 1권 Raw Socket chapter를 보시면 될거 같구요... 물론 다른 곳에도 많겠지만...
나를 죽이지 않는 모든 것은 나를 강하게 할 뿐이다.
허접하지만... 제가 짠 핑프로브입니다.
저도 같은 프로젝트하는데 ^^
#include "ping.h" char send_buf[1500]; //보내는 버퍼 char recv_buf[1500]; //받는 버퍼 int g_id = 0; //getpid()값 저장. 내가 보낸 ping만 받기위해 struct sockaddr_in dest_addr; //목적지 소켓구조체 struct sockaddr_in src_addr; //내 소켓구조체 pthread_t p_thread[2]; //쓰레드 id, [0]번 send, [1]번 recv unsigned short icmp_cksum(u_short *addr, int len) //ip체크섬 무시 -_-; { register int nleft = len; register u_short *w = addr; register int sum = 0; u_short answer = 0; while(nleft>1){ sum += *w++; nleft -= 2; } if(nleft==1){ *(u_char *)(&answer) = *(u_char *)w; sum == answer; } sum = (sum>>16) + (sum&0xffff); sum += (sum>>16); answer = ~sum; return(answer); } void sig_alrm() //ping 보내기를 마친지 sleep(x)초 후에 호출됨 { pthread_detach(p_thread[1]); //[1](recv) 쓰레드를 죽인다 } int init() //ping 전체모듈을 준비하는 부분 { int i; connect_db(); //db 연결 g_id = getpid(); //내가 보낸 ping을 확인하기위해 getpid() 저장 init_ping_node(); //ping_node 생성 get_addr(); //db에서 ip를 읽어오는 부분 for(i=0; i<9; i++) insert_ping_node(ipaddr[i]); //읽어온 ip 저장 signal(SIGALRM, &sig_alrm); //signal 선언 memset(&dest_addr, 0, sizeof(struct sockaddr_in)); //목적지 구조체 초기화 dest_addr.sin_family = AF_INET; dest_addr.sin_port = 0; return 0; } void init_ping_node(void) //ping 노드 초기화하는 부분 { ping_head = (PING_NODE *)malloc(sizeof(PING_NODE)); ping_tail = (PING_NODE *)malloc(sizeof(PING_NODE)); ping_head->next = ping_tail; ping_head->prev = ping_head; ping_tail->next = ping_tail; ping_tail->prev = ping_head; } PING_NODE *insert_ping_node(char str[]) //새로운 노드 삽입 { PING_NODE *s; s = (PING_NODE *)malloc(sizeof(PING_NODE)); strcpy(s->addr, str); //str로 넘어온놈 ip에 저장 s->check = 'N'; //기본 셋팅 N //새로운 노드는 가장 뒤에 붙인다. ping_tail->prev->next = s; s->prev = ping_tail->prev; s->next = ping_tail; ping_tail->prev = s; return s; } void *send_ping(void *arg) //ping 보내는 쓰레드, 인자값으로 보내는 소켓을 받는다 { struct icmphdr *icmp; int sockfd = *((int *)arg); //보내는 소켓을 sockfd에 저장 static int g_seq = 0; //icmp 시퀀스 넘버 PING_NODE *s; for(s=ping_head->next; s!=ping_tail; s=s->next) //head 다음부터 tail전까지 모든 ip에 핑을 보낸다 { icmp = (struct icmphdr *)send_buf; icmp->type = ICMP_ECHO; icmp->code = 0; icmp->un.echo.id = g_id; //내 pid icmp->un.echo.sequence = g_seq++; icmp->checksum = 0; icmp->checksum = icmp_cksum((unsigned short *)icmp, 16); //체크섬 dest_addr.sin_addr.s_addr = inet_addr(s->addr); //목적지 ip가 계속 바뀐다 if(sendto(sockfd, send_buf, 16, 0, (struct sockaddr *)&dest_addr, sizeof(dest_addr))<=0) perror("sendto: "); } sleep(1); //ping를 다 send 한후 1초 기다린다 sig_alrm(); //signal 호출 } void recv_icmp(char *buf, int totlen) //받은 ping 을 처리하는 부분 { int iplen, icmplen; struct iphdr *ip; struct icmphdr *icmp; int count=0; PING_NODE *s; s=ping_head->next; ip = (struct iphdr *)buf; iplen = ip->ihl*4; icmp = (struct icmphdr *)(buf + iplen); if(icmp->type == ICMP_ECHOREPLY){ //ping에 대한 reply 인가? if(icmp->un.echo.id == g_id) //identified가 내 pid와 같은가? { for(count=0; count<icmp->un.echo.sequence; count++) //시퀀스만큼 이동 s=s->next; if(s!=ping_tail) //찾은 부분이 끝이 아니면 check를 Y로 체크해서 살아있다고 표시 s->check = 'Y'; } } } void *recv_ping(void *arg) //ping을 받는 쓰레드, 인자값으로 받는 소켓을 받는다 { int len, sz; int sockfd = *((int *)arg); //받는 소켓을 sockfd에 저장 memset(recv_buf, '\0', sizeof(recv_buf)); while(1) { if((recvfrom(sockfd, recv_buf, sizeof(recv_buf), 0, (struct sockaddr *)&src_addr, &len))<=0) perror("recvfrom: "); recv_icmp(recv_buf, sz); //받은 데이터를 처리부분에 넘긴다 } } int ping(void) { int thr_id; int status; int sendfd, recvfd; if((sendfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP))<0){ //ping을 보내는 소켓을 만든다 fprintf(stderr, "ERROR: Opening raw socket. (need UID 0)\n"); exit(0); } if((recvfd = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP))<0){ //ping을 받는 소켓을 만든다 fprintf(stderr, "ERROR: Opening raw socket. (need UID 0)\n"); exit(0); } init(); //전체 준비부분 실행 thr_id = pthread_create(&p_thread[0], NULL, send_ping, (void *)&sendfd); //ping을 보내는 쓰레드 실행 thr_id = pthread_create(&p_thread[1], NULL, recv_ping, (void *)&recvfd); //ping을 받는 쓰레드 실행 //ping을 보내는 쓰레드의 종료를 처리 (detach로 죽이기 때문에 처리 안됨) pthread_join(p_thread[0], (void *)&status); pthread_join(p_thread[1], (void *)&status); //ping을 받는 쓰레드의 종요를 처리(detach로 죽이기때문에 안됨 -_-; }몇군데 문제점이 있습니다.
일단 여러개 가져다가 고쳐쓰다보니 signal도 의미가 없어지고 -_-;
pthread_detach(p_thread[1]) 가 쓰레드 죽이는건줄 알았는데... 죽던말던 신경 안쓴다는거라네요.
즉 p_thread[1]은 계속 receive에서 블록되있습니다.
지금까지는 문제가 없어서... 제가 갑자기 UI로 옮겨가서 놔둔상태이지만, 발표회때 문제생기면 ㅡㅡㅋ
모두모두 감사합니다 ^^*
덕분에 조금 실마리가 풀린거 같습니다.......
지금은 ping source 분석중이구요,,,
snmpget, snmpwalk, snmpd, snmp_api.h 분석을 마쳤구요,,,,
궁금한거 있음 또 올릴게염 ^.,^
모두모두 즐프하세여~~~~~
글고 cjy1126님 함께해여,,,ㅋㅋㅋ ^_____^;;;
hi!! nice to meet you!
thanks~!
제가 보기에도. 핑을 직접 짜서 사용하시는것이 맞다고 봅니다.
ping정도는 직접 작성하시는것이 작성하는 프로그램이 제대로 돌아가는
첫번째 요건이라고 봅니다.
님께서 질문하신 방법의 젤 쉬운 방법이야.
FILE *fp; char buf[1024]; fp = popen("ping 127.0.0.1", "r"); while (fgets(buf, fp)) { printf("%s\n", buf); } pclose(fp);위 예제에서 printf 부분만 수정하셔도 될듯 하지만,
popen을 모르시는 분들이 의외로 계시는군요. ^^;
P.S. cjy1126, flatony 두분혹시 같이 프로젝트 하시는거 아니에요? :)
댓글 달기