walk




void req_send(snmp_req *req)  
{
int ret = 0, n = 0, m = 0;
int liberr, syserr;
struct snmp_session Session;
struct snmp_pdu *pdu;
oid anOID[MAX_OID_LEN];
void *sessp = NULL;
struct timeval timeout;
timeout.tv_usec = 0;
timeout.tv_sec = req->snmpdata->timeout;
int fds = 0, block = 1;  
fd_set fdset;
char* ipaddr;
char* community;
char portstr[10] = { 0 };


if (!req->sessp)
{
snmp_sess_init(&Session);  

Session.version = req->snmpdata->version;
Session.retries = req->snmpdata->retries;
Session.callback = snmp_get_callback;
Session.callback_magic = req;
Session.timeout = req->snmpdata->timeout * 1000000L;
Session.remote_port = req->snmpdata->port;


n = wcslen(req->snmpdata->ipaddr);
m = sprintf(portstr, "%u",req->snmpdata->port);
ipaddr = calloc(sizeof(char), n + m + 1);//
ret = wcstombs(ipaddr, req->snmpdata->ipaddr, n);
*(ipaddr+n) = ':';//
strcat(ipaddr, portstr);//
Session.peername = ipaddr;
if (-1 == ret) {
req->snmpdata->result = XFAERR_WCSTOMBS;
ret = -1;
//LOG 出力
goto done;
}


n = wcslen(req->snmpdata->community);
community = calloc(sizeof(char), n);
ret = wcstombs(community, req->snmpdata->community, n);
Session.community = (u_char*)community;
if (-1 == ret) {
req->snmpdata->result = XFAERR_WCSTOMBS;
//LOG 出力
ret = -1;
goto done;
}


Session.community_len = strlen((char*)Session.community);


sessp = snmp_sess_open(&Session);
if (sessp == NULL) {  
/* Error codes found in open calling argument */  
snmp_error(&Session, &syserr , &liberr, NULL);  
req->snmpdata->syserr = syserr;  
req->snmpdata->liberr = liberr;
req->snmpdata->result = XFAERR_NETSNMPERR;
ret = -1;
goto done;  

req->sessp = sessp;
}
sessp = req->sessp;
if (req->snmpdata->walkflag == XFA_SNMP_GETNEXT_RESPONE) {
pdu = snmp_pdu_create(SNMP_MSG_GETNEXT);
if (!pdu) {
g_errline = __LINE__;
req->snmpdata->syserr = errno;
req->snmpdata->result = XFAERR_NETSNMPERR;
ret = -1;
goto done;
}
if (req->snmpdata->data) {//add to end or begine 
for(n = 0; n < req->snmpdata->data->oidlen; n++) {
anOID[n] = *(req->snmpdata->data->oid+n);
}
snmp_add_null_var(pdu, anOID, req->snmpdata->data->oidlen);

else {
for(n = 0; n < req->snmpdata->oidlen; n++) {
anOID[n] = *(req->snmpdata->oid+n);
}
snmp_add_null_var(pdu, anOID, req->snmpdata->oidlen);
}
} else {
pdu = snmp_pdu_create(SNMP_MSG_GET);
if (!pdu) {
g_errline = __LINE__;
req->snmpdata->syserr = errno;
req->snmpdata->result = XFAERR_NETSNMPERR;
ret = -1;
goto done;
}
for(n = 0; n < req->snmpdata->oidlen; n++) {
anOID[n] = *(req->snmpdata->oid+n);
}
snmp_add_null_var(pdu, anOID, req->snmpdata->oidlen);
}


if (0 == snmp_sess_send(sessp, pdu)) {
snmp_sess_error(sessp, &syserr,&liberr, NULL);
g_errline = __LINE__;
req->snmpdata->liberr = liberr;
req->snmpdata->result = XFAERR_NETSNMPERR;
req->snmpdata->syserr = syserr;
snmp_free_pdu(pdu);
ret = -1;
goto done;
}
req->status = 1;
snmp_sess_select_info(sessp, &fds, &fdset, &timeout, &block);
req->snmpfd = fds - 1;


done:
if (ret == -1) {
snmp_sess_close(sessp);
if (Session.peername) {
free(Session.peername);
Session.peername = NULL;
}
if (Session.community) {
free(Session.community);
Session.community = NULL;
}


notify_ap(req); //bug when snmp_sess_send failed but callbalk function been called anyway.
}
return;  



void res_read(int snmpfd)
{  
fd_set fdset;
int liberr, syserr;
snmp_req *tmp = NULL;


//ここでg_reqListをロックしない
tmp = g_reqList;
while(tmp) {
if (snmpfd == tmp->snmpfd) {
break;
}
tmp = tmp->next;
}


if (!tmp) {
goto done;
}


FD_ZERO(&fdset);
FD_SET(snmpfd, &fdset);
if (snmp_sess_read(tmp->sessp, &fdset) == -1) {
snmp_sess_error(tmp->sessp, &syserr,&liberr, NULL);
tmp->snmpdata->liberr = liberr;
tmp->snmpdata->syserr = syserr;
tmp->snmpdata->result = XFAERR_NETSNMPERR;
}

if (tmp->status == 2) {
notify_ap(tmp);
snmp_sess_close(tmp->sessp);//sessp re creat
}
//snmp_sess_close(tmp->sessp);//sessp re creat
done:
return;
}


void *snmp_get_thread(void *arg)
{
fd_set fdset;
int sdAll[FD_SETSIZE] = { 0 };
int i, j, m, n;
char buf[64];
int maxfd = -1;
snmp_req *tmp, *sendtmp;
struct timeval timeout;


while(g_terminateflag) {
FD_ZERO(&fdset);
FD_SET(g_reqfd, &fdset);
maxfd = g_reqfd;
i = 0;


//ここでg_reqListをロックしない
sendtmp = tmp = g_reqList;
while (tmp) {
if (tmp->status == 1) {
if (tmp->snmpfd > maxfd) {
maxfd = tmp->snmpfd;
}
FD_SET(tmp->snmpfd, &fdset);
sdAll[i++] = tmp->snmpfd;
}
tmp = tmp->next;
}


if ( (n = select(maxfd+1, &fdset, NULL, NULL, &timeout)) > 0) {
if (FD_ISSET(g_reqfd, &fdset)) {
while (1) {
m = recvfrom(g_reqfd, buf, sizeof(buf), 0, NULL, NULL);
if (m <= 0) {
break;
}
}


while(sendtmp) {//ここでg_reqListをロックしない
if (2 != sendtmp->status) {
req_send(sendtmp);
}
sendtmp = sendtmp->next;
}
} else {
for (j = 0; j < i; j ++) {
if (FD_ISSET(sdAll[j], &fdset)) {
res_read(sdAll[j]);
}
}
}
} else if (n == -1) {

} else {
res_read_timeout();
}
}


return (void *)1;
}


int xfa_snmp_init(void)
{
int ret = 0;
void *res = NULL;
int s = 1, tnum;
pthread_attr_t attr;
socklen_t addrlen;
struct sockaddr_in addr;
#ifdef WIN32
SYSTEM_INFO si;
#endif


//ミューテックス初期化
ret = pthread_mutex_init(&g_mutex_ini, NULL);
if (ret) {
g_errline = __LINE__;
ret = XFAERR_BADMUTEX;
goto done;
}


pthread_mutex_lock(&g_mutex_ini);
if (g_initflag == 1) {
pthread_mutex_unlock(&g_mutex_ini);
goto done;
}
pthread_mutex_unlock(&g_mutex_ini);


SOCK_STARTUP;


ret = pthread_mutex_init(&g_mutex_req, NULL);
if (ret) {
g_errline = __LINE__;
ret = XFAERR_BADMUTEX;
goto done;
}


g_reqfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (g_reqfd == -1) {
g_errline = __LINE__;
ret = XFAERR_BADSOCKET;
goto done;
}
if ((ret = ioctl(g_reqfd, FIONBIO, &s)) < 0) {
g_errline = __LINE__;
ret = XFAERR_BADSOCKET;
goto done;
}
memset(&addr, 0, sizeof(struct sockaddr_in));
addrlen = sizeof(struct sockaddr_in);
addr.sin_family = AF_INET;
addr.sin_port = htons(0);
addr.sin_addr.s_addr = inet_addr("127.0.0.1");
ret = bind(g_reqfd, (struct sockaddr *) &addr, addrlen);
if (ret != 0) {
g_errline = __LINE__;
ret = XFAERR_BADSOCKET;
goto done;
}
addrlen = sizeof(struct sockaddr_in);
ret = getsockname(g_reqfd, (struct sockaddr *) &g_listenaddr, &addrlen);
if (ret != 0) {
g_errline = __LINE__;
ret = XFAERR_BADSOCKET;
goto done;
}


ret = pthread_attr_init(&attr);
if (ret != 0) {
g_errline = __LINE__;
ret = XFAERR_BADTHREAD;
goto done;
}
#ifndef WIN32  //LINUX,HP-UX 対応  
for (tnum = 0; tnum < MAX_THREAD_COUND; tnum++) {
g_pThreadInfo[tnum].thread_num = tnum + 1;
ret = pthread_create(&g_pThreadInfo[tnum].thread_id, &attr, snmp_get_thread, &g_pThreadInfo[tnum]);
if (ret != 0) {
g_errline = __LINE__;
ret = XFAERR_BADTHREAD;
goto done;
}
}
g_terminateflag = 1;
ret = pthread_attr_destroy(&attr);
if (ret != 0) {
g_errline = __LINE__;
ret = XFAERR_BADTHREAD;
goto done;
}
#else  //WINODWS 対応
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
#endif


done:
if (ret < 0) {
SOCK_CLEANUP;
if (g_reqfd) {
close(g_reqfd);
g_reqfd = 0;
}
pthread_mutex_destroy(&g_mutex_req);
pthread_mutex_destroy(&g_mutex_ini);
for (tnum = 0; tnum < MAX_THREAD_COUND; tnum++) {
s = pthread_join(g_pThreadInfo[tnum].thread_id, &res);
}


} else {
g_terminateflag = 1;
pthread_mutex_lock(&g_mutex_ini);
g_initflag = 1;
pthread_mutex_unlock(&g_mutex_ini);
}
return ret;
}


xfa_snmpdata* xfa_snmpdata_alloc(wchar_t* ipaddr, 
unsigned short port, 
long version,
wchar_t* community,
unsigned long* oid, 
int retries,
long timeout,
int walkflag,
int oidlen)

xfa_snmpdata* snmpdata = NULL;
int ret = 0;


snmpdata = (xfa_snmpdata*)calloc(sizeof(xfa_snmpdata), 1);
if (!snmpdata) {
ret = -1;
goto done;
}


//ipv6チェック必要
if (ipaddr) {
if (wcschr(ipaddr, L':')) {
ret = -1;
goto done;
}
snmpdata->ipaddr = ipaddr;
} else {
ret = -1;
goto done;
}
snmpdata->port = port;


if (!oidlen || oidlen > 255) {
ret = -1;
goto done;
}
snmpdata->oidlen = oidlen;

if (walkflag != XFA_SNMP_GET_RESPONE && walkflag != XFA_SNMP_GETNEXT_RESPONE) {
ret = -1;
goto done;
}
snmpdata->walkflag = walkflag;


if (version != XFA_SNMP_VERSION_1 && version != XFA_SNMP_VERSION_2c) {
ret = -1;
goto done;
}
snmpdata->version = version;


snmpdata->community = community;

if (oid) {
snmpdata->oid = oid; 
} else {
ret = -1;
goto done;
}

if (retries < 0) {
ret = -1;
goto done;
}
snmpdata->retries = retries;

if (timeout < 0) {
ret = -1;
goto done;
}
snmpdata->timeout = timeout;


snmpdata->eventfd = 0;
snmpdata->result = 0;
snmpdata->liberr = 0;
snmpdata->syserr = 0;
snmpdata->data = NULL;


done:
if (ret < 0) {
if (snmpdata) {
free(snmpdata);
snmpdata = NULL;
}
return NULL;
} else {
return snmpdata;
}
}


int xfa_snmp_get(xfa_snmpdata *data)
{
snmp_req* req = NULL;
int ret = 0;
int eventfd = 0, s = 1;


//INIT Check
pthread_mutex_lock(&g_mutex_ini);
if (!g_initflag) {
ret = XFAERR_NOINIT;
goto done;
}
pthread_mutex_unlock(&g_mutex_ini);


//NULL Check
if (!data) {
ret = XFAERR_BADARG;
goto done;
}


eventfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (eventfd == -1) {
ret = XFAERR_BADSOCKET;
goto done;
}
if ((ret = ioctl(eventfd, FIONBIO, &s)) < 0) {
g_errline = __LINE__;
ret = XFAERR_BADSOCKET;
goto done;
}


if (!(req = (snmp_req*)calloc(sizeof(snmp_req), 1))) {
ret = XFAERR_NOBUFS;
goto done;
}
req->snmpdata = data;
req->snmpfd = 0;
req->sessp = NULL;
req->status = 0;
req->snmpdata->eventfd = eventfd;


pthread_mutex_lock(&g_mutex_req);
queue_add((void**)&g_reqList,(void*)req);
pthread_mutex_unlock(&g_mutex_req);


//WorkerThreadへ通知する
if (sendto(eventfd, "S", 1, 0,(struct sockaddr *)&g_listenaddr,sizeof(g_listenaddr)) == -1) {
ret = XFAERR_BADSOCKET;
goto done;
}


done:
if (ret < 0) {
if (eventfd) {
close(eventfd);
eventfd = 0;
}
if (data){
data->eventfd = 0;
}
if (req) {
free(req);
req = NULL;
}
return ret;
} else {
return eventfd;
}
}


void res_read_timeout(void)
{
snmp_req *tmp = NULL;


//ここでg_reqListをロックしない
tmp = g_reqList;
while (tmp) {
if (tmp->status != 0) {
snmp_sess_timeout(tmp->sessp);
}
tmp= tmp->next;
}
return;
}


int xfa_snmp_cleanup(void)
{
int tnum, ret = 0;
void* res = NULL;
snmp_req *reqtmp1 = NULL, *reqtmp2 = NULL;
xfa_mibdata *mibtmp1 = NULL, *mibtmp2 = NULL;


if (!g_initflag) {
ret = XFAERR_NOINIT;
goto done;
}
pthread_mutex_lock(&g_mutex_ini);
g_initflag = 0;
if (g_reqfd) {
close(g_reqfd);
g_reqfd = -1;
}
//WorkerThread終了マーク設定
g_terminateflag = 0;


//WorkerThread終了を待つ
for (tnum = 0; tnum < MAX_THREAD_COUND; tnum++) {
pthread_join(g_pThreadInfo[tnum].thread_id, &res);
}
//資源クリーン
pthread_mutex_lock(&g_mutex_req);
reqtmp1 = g_reqList;
while (reqtmp1) {
if (reqtmp1->sessp) { //Net snmp free
free(reqtmp1->sessp);
reqtmp1->sessp = NULL;
}
if (reqtmp1->snmpdata) {
if (reqtmp1->snmpdata->data) {
mibtmp1 = reqtmp1->snmpdata->data;
while(mibtmp1) {
if (mibtmp1->str){
free(mibtmp1->str);
mibtmp1->str = NULL;
}
if (mibtmp1->value){
free(mibtmp1->value);
mibtmp1->value = NULL;
}
mibtmp2 = mibtmp1->next;
free(mibtmp1);
mibtmp1 = mibtmp2;
}
}
if (reqtmp1->snmpdata->eventfd) {
close(reqtmp1->snmpdata->eventfd);
reqtmp1->snmpdata->eventfd = 0;
}
}
queue_del((void**)&g_reqList, (void*)reqtmp1);
reqtmp2 = reqtmp1->next;
free(reqtmp1); //bug
reqtmp1 = reqtmp2;
}
g_reqList = NULL;
pthread_mutex_unlock(&g_mutex_req);


SOCK_CLEANUP;
pthread_mutex_unlock(&g_mutex_ini);
pthread_mutex_destroy(&g_mutex_req);
pthread_mutex_destroy(&g_mutex_ini);


done:
return ret;
}


int xfa_mibdata_to_str(
  xfa_mibdata *data,
  unsigned int codePage,
  wchar_t** value)
{
int n, m, i;
int isHex = 0;
unsigned char c;
char *s;
unsigned int tt, uu, ss, mm, hh;
char str[1024] = { 0 };


if (!data || !value || !data->value || !data->str) {
return XFAERR_BADARG;
}
setlocale(LC_ALL, /*"ca_ES.utf8"*/NULL);//set codepage
//str = data->str;


switch(data->type) {
case XFA_MIBTYPE_OCTETSTRING:
case XFA_MIBTYPE_OPAQUE:
for (i = 0; i < data->len; i++) {
m =(int) *((unsigned char*)data->value+i);
if (isprint(m)) {
continue;
} else {
isHex = 1;
break;
}
}
if (isHex) {
n = 0;
str[n++] = '0';
str[n++] = 'x';
for (i = 0; i < data->len; i++) {
c = *((unsigned char*)data->value+i);
str[n++] = dig2hex[(c & 0xf0) >> 4];
str[n++] = dig2hex[c & 0x0f];
str[n++] = L':';
}
str[n-1] = '\0';
} else {
for (i = 0; i <data->len; i++) {
str[i] = *(((unsigned char*)data->value)+i);
}
str[i] = '\0';
}
break;
case XFA_MIBTYPE_IPADDRESS:
sprintf(str, "%u.%u.%u.%u", *((unsigned char*)data->value+0), *((unsigned char*)data->value+1), *((unsigned char*)data->value+2), *((unsigned char*)data->value+3));
break;


case XFA_MIBTYPE_OBJECT_IDENTIFIER:
if (data->len > 128) {
break;
}
str[0] = '\0';
for (i = 0; i < data->len/8; i++) {
sprintf(s,"%d", *((int*)data->value+(i*2)));
strcat(str,s);
strcat(str,".");
}
s = strrchr(str,(int)'.');
*s = '\0';
break;
case XFA_MIBTYPE_TIMETICKS:
// TimeTicks
//L"hh:mm:ss.uu"
tt = *((unsigned long *)data->value);
ss = tt / 100; uu = tt % 100;
mm = ss / 60;  ss = ss % 60;
hh = mm / 60;  mm = mm % 60;
(void) sprintf(str, "%u:%02u:%02u.%02u", hh, mm, ss, uu);
break;
default:break;
}


mbstowcs(data->str, str, strlen(str));
*value = data->str;
return XFAERR_NOERR;
}


int xfa_mibdata_to_int(
  xfa_mibdata *data,
  int *value)
{
if (!data || !value || data->type != XFA_MIBTYPE_INTEGER) {
return XFAERR_BADARG;
} else {
if (data->value) {
*value = *((int*)data->value);
} else {
return XFAERR_BADARG;
}
}
return XFAERR_NOERR;
}




int xfa_mibdata_to_uint(
xfa_mibdata *data,
unsigned int *value)
{
if (!data || !value || data->type != 0x41 || data->type != 0x42) {
return XFAERR_BADARG;
} else {
*value = *((unsigned int*)data->value);
}
return XFAERR_NOERR;
}




int xfa_mibdata_to_ulonglong(
xfa_mibdata *data,
unsigned long long *value)


{
if (!data || !value || data->type != XFA_MIBTYPE_COUNTER64) {
return XFAERR_BADARG;
} else {
*value = *((unsigned long long*)data->value);
}
return XFAERR_NOERR;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章