

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <string.h>
#include <unistd.h>

#include<almemsys/almemsys.h>
#include "jpreturn.h"
#include "version.h"

#define MIB_BUFLEN 256

// debug option
// #define SNMP_COM



int main(int argc, char * argv[])
{
int i, timeout;
char * buf;
extern char *optarg;

char * name;
char * host;
char * getoid;

struct snmp_session session, *ss;
struct snmp_pdu *pdu;
struct snmp_pdu *response;

struct tree    *tp;

timeout = 0;

oid anOID[MAX_OID_LEN];
size_t anOID_len = MAX_OID_LEN;

struct variable_list *vars;
int status;

/* init buf */
buf = (char *)calloc(MIB_BUFLEN, sizeof(char));
name = (char *)calloc(MIB_BUFLEN, sizeof(char));
host = (char *)calloc(MIB_BUFLEN, sizeof(char));
getoid = (char *)calloc(MIB_BUFLEN, sizeof(char));


// optionの処理
while((i=getopt(argc,argv,"a:t:n:h:o:v:z"))!= EOF){
   switch(i){
      case 't': if(0 == ch_int2(optarg)){
                   timeout = strtol(optarg, (char **)NULL, 10);
                   }
              break;
      case 'n': if(optarg != NULL){
                   name = safe_memcpy(name, optarg, 1024);
                   }
                else{
                   name = safe_memcpy(name, "public", 1024);
                   }
              break;
      case 'h': if(optarg != NULL){
                   host = safe_memcpy(host, optarg, 1024);
                   }
                else{
                   host = safe_memcpy(host, "localhost", 1024);
                   }
              break;
      case 'o': if(optarg != NULL){
                   getoid = safe_memcpy(getoid, optarg, 1024);
                   }
                else{
                   getoid = safe_memcpy(getoid, "not", 1024);
                   }
              break;

      default : printf("snmp_command-%s $snmp_command -n <section_name> -h <host:port> -o <OID> -t <timout>\n",VERSION);
              free(buf);
              free(name);
              free(host);
              free(getoid);
              exit(1);
              break;
      }
   }

// printf("host = <%s> timeout = <%d> secname = <%s> oid = <%s>\n", host, timeout, name, getoid);

// snmpライブラリーの初期化
init_snmp("sitar_snmp");

// snmp セッションの初期化
snmp_sess_init(&session);
session.peername = strdup(host);

// セッションのタイムアウト秒設定
if(timeout <= 0){
   timeout = 1;
   }
else if(timeout > 20){
   timeout = 20;
   }

#ifdef SNMP_COM
printf("SNMP_COM: main(): timeout %d sec \n", timeout);
#endif

// セッションタイムアウトを秒単位で設定
session.timeout = (long)(1000000 * timeout);
session.retries = 0;

// snmpのプロトコルバージョンを1に設定
session.version = SNMP_VERSION_1;
session.community = (unsigned char *)name;
session.community_len = (int)strlen((char *)session.community);

// snmpセッションを実行
ss = snmp_open(&session);

#ifdef SNMP_COM
printf("SNMP_COM: main(): SESSION LOCL PEER NO <%s> TIMEOUT <%ld> RETRIES <%d>\n",
   session.peername, session.timeout, session.retries);
#endif

// セッションが正常に確立出来ない場合
if(!ss){
// snmp_perror("ack");
// snmp_log(LOG_ERR, "snmp session not open.\n");
   printf("SNMP_ERR: %s %s %s\n", SNMP_25, host, getoid);
   free(buf);
   free(name);
   free(host);
   free(getoid);
   return -1;
   }
// セッションが正常に確立出来た
else{
   #ifdef SNMP_COM
   printf("SNMP_COM: main(1): %s %s %s\n", SNMP_26, host, getoid);
   #endif
   }


// make PUD
pdu = snmp_pdu_create(SNMP_MSG_GET);
if(!read_objid(getoid, anOID, &anOID_len)){
   snmp_perror(getoid);
   printf("SNMP_ERR: %s %s %s\n", SNMP_27, host, getoid);
   free(buf);
   free(name);
   free(host);
   free(getoid);
   return -1;
   }

if((tp = get_tree(anOID, anOID_len, get_tree_head()))==NULL){
   printf("SNMP_ERR: %s %s %s\n", SNMP_28, host, getoid);
   free(buf);
   free(name);
   free(host);
   free(getoid);
   return -1;
   }

// debug infomationi
#ifdef SNMP_COM
print_mib_tree(stdout, tp, 1000000);
print_objid(anOID, anOID_len);
print_description(anOID, anOID_len, 1000000);
#endif


snmp_add_null_var(pdu, anOID, anOID_len);

// セッションとの通信
status = snmp_synch_response(ss, pdu, &response);


// セッションから正常にステータスを得た場合
if(status == STAT_SUCCESS && response->errstat == SNMP_ERR_NOERROR){
   for(vars = response->variables; vars; vars = vars->next_variable){
      snprint_value(buf, MIB_BUFLEN, vars->name, vars->name_length, vars);
      #ifdef SNMP_COM
      printf("SNMP_COM: main(): buf = %s\n", buf);
      print_variable(vars->name, vars->name_length, vars);
      #endif
      } 
   }
else{
   // セッションとの通信は出来たが、ステータスが得られない場合
   if(status == STAT_SUCCESS){
      printf("SNMP_ERR: snmp error code: %s\n", snmp_errstring(response->errstat));
      free(buf);
      free(name);
      free(host);
      free(getoid);
      snmp_close(ss);
      return -1;
      }
   // セッションとの通信が得られない
   else{
      snmp_sess_perror("snmpget", ss);
      printf("SNMP_ERR: %s %s %s\n", SNMP_31, host, getoid);
      free(buf);
      free(name);
      free(host);
      free(getoid);
      snmp_close(ss);
      return -1;
      }
   }

// SNMPとのセッションを閉じる
if(response){
   #ifdef SNMP_COM
   printf("SNMP_COM: main(5-2): %s %s %s\n", "session close", host, getoid);
   #endif
   snmp_free_pdu(response);
   snmp_close(ss);
   }

// ここに来るのは正常な証拠です。
printf("%s\n", buf);


free(buf);
free(name);
free(host);
free(getoid);

return 0;
}





