void
snmp_log_string (int priority, const char *string)
{
    char sbuf[40];
    struct snmp_log_message slm;

#if HAVE_SYSLOG_H
  if (do_syslogging) {
    syslog(priority, string);
  }
#endif

  if (do_log_callback) {
      slm.priority = priority;
      slm.msg = string;
      snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, &slm);
  }

  if (do_filelogging || do_stderrlogging) {

    if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_LOG_TIMESTAMP) && newline) {
      sprintf_stamp(NULL, (char *)&sbuf);
    } else {
      strcpy(sbuf, "");
    }
    newline = string[strlen(string)-1] == '\n';

    if (do_filelogging)
      fprintf(logfile, "%s%s", sbuf, string);

    if (do_stderrlogging)
      fprintf(stderr, "%s%s", sbuf, string);
  }
}
Exemple #2
0
/*
 * check a session validity for connectivity to the master agent.  If
 * not functioning, close and start attempts to reopen the session 
 */
void
agentx_check_session(unsigned int clientreg, void *clientarg)
{
    netsnmp_session *ss = (netsnmp_session *) clientarg;
    if (!ss) {
        if (clientreg)
            snmp_alarm_unregister(clientreg);
        return;
    }
    DEBUGMSGTL(("agentx/subagent", "checking status of session %p\n", ss));

    if (!agentx_send_ping(ss)) {
        snmp_log(LOG_WARNING,
                 "AgentX master agent failed to respond to ping.  Attempting to re-register.\n");
        /*
         * master agent disappeared?  Try and re-register.
         * close first, just to be sure .
         */
        agentx_unregister_callbacks(ss);
        agentx_close_session(ss, AGENTX_CLOSE_TIMEOUT);
        snmp_alarm_unregister(clientreg);       /* delete ping alarm timer */
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                            SNMPD_CALLBACK_INDEX_STOP, (void *) ss);
        snmp_close(main_session);
        main_session = NULL;
        agentx_reopen_session(0, NULL);
    } else {
        DEBUGMSGTL(("agentx/subagent", "session %p responded to ping\n",
                    ss));
    }
}
Exemple #3
0
int
in_a_view(oid		  *name,      /* IN - name of var, OUT - name matched */
          size_t	  *namelen,   /* IN -number of sub-ids in name*/
          struct snmp_pdu *pdu,       /* IN - relevant auth info re PDU */
          int	           type)      /* IN - variable type being checked */
{

  struct view_parameters view_parms;
  view_parms.pdu = pdu;
  view_parms.name = name;
  if (namelen)
      view_parms.namelen = *namelen;
  else
      view_parms.namelen = 0;
  view_parms.errorcode = 0;

  if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW)
    return 0;		/* Enable bypassing of view-based access control */

  /* check for v1 and counter64s, since snmpv1 doesn't support it */
  if (pdu->version == SNMP_VERSION_1 && type == ASN_COUNTER64)
    return 5;
  switch (pdu->version) {
  case SNMP_VERSION_1:
  case SNMP_VERSION_2c:
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
  case SNMP_VERSION_3:
#endif
    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_ACM_CHECK,
                        &view_parms);
    return view_parms.errorcode;
  }
  return 1;
}
Exemple #4
0
/* in_a_view: determines if a given snmp_pdu is ever going to be allowed to do
   anynthing or if it's not going to ever be authenticated. */
int
check_access(struct snmp_pdu *pdu)      /* IN - pdu being checked */
{
  struct view_parameters view_parms;
  view_parms.pdu = pdu;
  view_parms.name = 0;
  view_parms.namelen = 0;
  view_parms.errorcode = 0;

  if (pdu->flags & UCD_MSG_FLAG_ALWAYS_IN_VIEW)
    return 0;		/* Enable bypassing of view-based access control */

  switch (pdu->version) {
  case SNMP_VERSION_1:
  case SNMP_VERSION_2c:
#ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
  case SNMP_VERSION_3:
#endif
    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_ACM_CHECK_INITIAL,
                        &view_parms);
    return view_parms.errorcode;
  }
  return 1;
}
void
update_config(void)
{
    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_PRE_UPDATE_CONFIG, NULL);
    free_config();
    read_configs();
}
Exemple #6
0
/*
 * check a session validity for connectivity to the master agent.  If
 * not functioning, close and start attempts to reopen the session
 */
void agentx_check_session (unsigned int clientreg, void *clientarg)
{
    netsnmp_session *ss = (netsnmp_session *) clientarg;

    if (!ss)
    {
        if (clientreg)
            snmp_alarm_unregister (clientreg);
        return;
    }
    DEBUGMSGTL (("agentx/subagent", "checking status of session %p\n", ss));

    if (!agentx_send_ping (ss))
    {
        snmp_log (LOG_WARNING, "AgentX master agent failed to respond to ping.  Attempting to re-register.\n");
        /*
         * master agent disappeared?  Try and re-register.
         * close first, just to be sure .
         */
        agentx_unregister_callbacks (ss);
        agentx_close_session (ss, AGENTX_CLOSE_TIMEOUT);
        snmp_alarm_unregister (clientreg);    /* delete ping alarm timer */
        snmp_call_callbacks (SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_INDEX_STOP, (void *) ss);
        register_mib_detach ();
        if (main_session != NULL)
        {
            remove_trap_session (ss);
            snmp_close (main_session);
            /*
             * We need to remove the callbacks attached to the callback
             * session because they have a magic callback data structure
             * which includes a pointer to the main session
             *    (which is no longer valid).
             *
             * Given that the main session is not responsive anyway.
             * it shoudn't matter if we lose some outstanding requests.
             */
            if (agentx_callback_sess != NULL)
            {
                snmp_close (agentx_callback_sess);
                agentx_callback_sess = NULL;

                subagent_init_callback_session ();
            }
            main_session = NULL;
            agentx_reopen_session (0, NULL);
        }
        else
        {
            snmp_close (main_session);
            main_session = NULL;
        }
    }
    else
    {
        DEBUGMSGTL (("agentx/subagent", "session %p responded to ping\n", ss));
    }
}
void
read_premib_configs (void)
{
  DEBUGMSGTL(("read_config","reading premib configuration tokens\n"));

  if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
    read_config_files(PREMIB_CONFIG);

  snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
                      SNMP_CALLBACK_POST_PREMIB_READ_CONFIG,
                      NULL);
}
int register_sysORTable_sess(oid *oidin,
			 size_t oidlen,
			 const char *descr,
			 struct snmp_session *ss)
{
  struct sysORTable **ptr=&table;
  struct register_sysOR_parameters reg_sysOR_parms;

    DEBUGMSGTL(("mibII/sysORTable", "sysORTable registering: "));
    DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen));
    DEBUGMSG(("mibII/sysORTable","\n"));

  while(*ptr != NULL)
    ptr = &((*ptr)->next);
  *ptr = (struct sysORTable *) malloc(sizeof(struct sysORTable));
  if ( *ptr == NULL ) {
	return SYS_ORTABLE_REGISTRATION_FAILED;
  }
  (*ptr)->OR_descr = (char *) malloc(strlen(descr)+1);
  if ( (*ptr)->OR_descr == NULL ) {
	free( *ptr );
	return SYS_ORTABLE_REGISTRATION_FAILED;
  }
  strcpy((*ptr)->OR_descr, descr);
  (*ptr)->OR_oidlen = oidlen;
  (*ptr)->OR_oid = (oid *) malloc(sizeof(oid)*oidlen);
  if ( (*ptr)->OR_oid == NULL ) {
	free( *ptr );
	free( (*ptr)->OR_descr );
	return SYS_ORTABLE_REGISTRATION_FAILED;
  }
  memcpy((*ptr)->OR_oid, oidin, sizeof(oid)*oidlen);
  gettimeofday(&((*ptr)->OR_uptime), NULL);
  (*ptr)->OR_sess = ss;
  (*ptr)->next = NULL;
  numEntries++;

  reg_sysOR_parms.name    = oidin;
  reg_sysOR_parms.namelen = oidlen;
  reg_sysOR_parms.descr   = descr;
  snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REG_SYSOR,
                                       &reg_sysOR_parms);

  return SYS_ORTABLE_REGISTERED_OK;
}
Exemple #9
0
int
log_handler_callback(netsnmp_log_handler* logh, int pri, const char *str)
{
	/*
	 * XXX - perhaps replace 'snmp_call_callbacks' processing
	 *       with individual callback log_handlers ??
	 */
    struct snmp_log_message slm;
    int             dodebug = snmp_get_do_debugging();

    slm.priority = pri;
    slm.msg = str;
    if (dodebug)            /* turn off debugging inside the callbacks else will loop */
        snmp_set_do_debugging(0);
    snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, &slm);
    if (dodebug)
        snmp_set_do_debugging(dodebug);
    return 1;
}
void
read_configs (void)
{

  char *optional_config = ds_get_string(DS_LIBRARY_ID, DS_LIB_OPTIONALCONFIG);
  char *type = ds_get_string(DS_LIBRARY_ID, DS_LIB_APPTYPE);

  DEBUGMSGTL(("read_config","reading normal configuration tokens\n"));
  
  if (!ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_READ_CONFIGS))
    read_config_files(NORMAL_CONFIG);

 /* do this even when the normal above wasn't done */
  if (optional_config && type)
    read_config_with_type(optional_config, type);

  snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_POST_READ_CONFIG,
                      NULL);
}
int unregister_sysORTable_sess(oid *oidin,
			 size_t oidlen,
			 struct snmp_session *ss)
{
  struct sysORTable **ptr=&table, *prev=NULL;
  int found = SYS_ORTABLE_NO_SUCH_REGISTRATION;
  struct register_sysOR_parameters reg_sysOR_parms;

    DEBUGMSGTL(("mibII/sysORTable", "sysORTable unregistering: "));
    DEBUGMSGOID(("mibII/sysORTable", oidin, oidlen));
    DEBUGMSG(("mibII/sysORTable","\n"));

  while(*ptr != NULL) {
    if ( snmp_oid_compare( oidin, oidlen, (*ptr)->OR_oid, (*ptr)->OR_oidlen) == 0 ) {
      if ( (*ptr)->OR_sess != ss )
	continue;	/* different session */
      if ( prev == NULL )
        table      = (*ptr)->next;
      else 
        prev->next = (*ptr)->next;

      free( (*ptr)->OR_descr );
      free( (*ptr)->OR_oid );
      free( (*ptr) );
      numEntries--;
      found = SYS_ORTABLE_UNREGISTERED_OK;
      break;
    }
    prev = *ptr;
    ptr = &((*ptr)->next);
  }

  reg_sysOR_parms.name    = oidin;
  reg_sysOR_parms.namelen = oidlen;
  snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREG_SYSOR,
                                       &reg_sysOR_parms);

  return found;
}
Exemple #12
0
int
add_trap_session(netsnmp_session * ss, int pdutype, int confirm,
                 int version)
{
    if (snmp_callback_available(SNMP_CALLBACK_APPLICATION,
                                SNMPD_CALLBACK_REGISTER_NOTIFICATIONS) ==
        SNMPERR_SUCCESS) {
        /*
         * something else wants to handle notification registrations 
         */
        struct agent_add_trap_args args;
        DEBUGMSGTL(("trap", "adding callback trap sink\n"));
        args.ss = ss;
        args.confirm = confirm;
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                            SNMPD_CALLBACK_REGISTER_NOTIFICATIONS,
                            (void *) &args);
    } else {
        /*
         * no other support exists, handle it ourselves. 
         */
        struct trap_sink *new_sink;

        DEBUGMSGTL(("trap", "adding internal trap sink\n"));
        new_sink = (struct trap_sink *) malloc(sizeof(*new_sink));
        if (new_sink == NULL)
            return 0;

        new_sink->sesp = ss;
        new_sink->pdutype = pdutype;
        new_sink->version = version;
        new_sink->next = sinks;
        sinks = new_sink;
    }
    return 1;
}
int
writeSystem(int action,
            u_char * var_val,
            u_char var_val_type,
            size_t var_val_len,
            u_char * statP, oid * name, size_t name_len)
{
    u_char         *cp;
    char           *buf = NULL, *oldbuf = NULL;
    int             count, *setvar = NULL;

    switch ((char) name[7]) {
    case VERSION_DESCR:
    case VERSIONID:
    case UPTIME:
        snmp_log(LOG_ERR, "Attempt to write to R/O OID\n");
        return SNMP_ERR_NOTWRITABLE;
    case SYSCONTACT:
        buf = sysContact;
        oldbuf = oldsysContact;
        setvar = &sysContactSet;
        break;
    case SYSTEMNAME:
        buf = sysName;
        oldbuf = oldsysName;
        setvar = &sysNameSet;
        break;
    case SYSLOCATION:
        buf = sysLocation;
        oldbuf = oldsysLocation;
        setvar = &sysLocationSet;
        break;
    case SYSSERVICES:
    case SYSORLASTCHANGE:
        snmp_log(LOG_ERR, "Attempt to write to R/O OID\n");
        return SNMP_ERR_NOTWRITABLE;
    default:
        return SNMP_ERR_GENERR; /* ??? */
    }

    switch (action) {
    case RESERVE1:             /* Check values for acceptability */
        if (var_val_type != ASN_OCTET_STR) {
            snmp_log(LOG_ERR, "not string\n");
            return SNMP_ERR_WRONGTYPE;
        }
        if (var_val_len > sizeof(sysLocation) - 1) {
            snmp_log(LOG_ERR, "bad length\n");
            return SNMP_ERR_WRONGLENGTH;
        }

        for (cp = var_val, count = 0; count < (int) var_val_len;
             count++, cp++) {
            if (!isprint(*cp)) {
                snmp_log(LOG_ERR, "not print %x\n", *cp);
                return SNMP_ERR_WRONGVALUE;
            }
						/* purpose      :  0012435 author :  Gavin.Lin  date :  2010-08-04 */
						/* description  :  Customer requirements                           */
						else
						{
							if ((*cp == 0x22) || (*cp == 0x25) || (*cp == 0x27) || (*cp == 0x5C))
							{
								return SNMP_ERR_WRONGVALUE;
							}						
						}
        }
        if (setvar != NULL && *setvar < 0) {
            /*
             * The object is set in a read-only configuration file.  
             */
            return SNMP_ERR_NOTWRITABLE;
        }
        break;

    case RESERVE2:             /* Allocate memory and similar resources */

        /*
         * Using static strings, so nothing needs to be done 
         */
        break;

    case ACTION:               /* Perform the SET action (if reversible) */

        /*
         * Save the old value, in case of UNDO 
         */
        strcpy(oldbuf, buf);
        memcpy(buf, var_val, var_val_len);
        buf[var_val_len] = 0;
        break;

    case UNDO:                 /* Reverse the SET action and free resources */

        strcpy(buf, oldbuf);
        oldbuf[0] = 0;
        break;

    case COMMIT:
        if (setvar != NULL) {
            *setvar = 1;
        }
        snmp_save_persistent(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
        (void) snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
                                   SNMP_CALLBACK_STORE_DATA, NULL);
        snmp_clean_persistent(netsnmp_ds_get_string
                              (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));

    case FREE:                 /* Free any resources allocated */

        /*
         * No resources have been allocated, but "empty" the 'oldbuf' 
         */
        oldbuf[0] = 0;
        break;
    }
    return SNMP_ERR_NOERROR;
}                               /* end of writeSystem */
/*******************************************************************-o-******
 */
int
main(int argc, char **argv)
{
	int	  rval		= SNMPERR_SUCCESS;
	size_t	  oldKu_len	= SNMP_MAXBUF_SMALL,
		  newKu_len	= SNMP_MAXBUF_SMALL,
		  oldkul_len	= SNMP_MAXBUF_SMALL,
		  newkul_len	= SNMP_MAXBUF_SMALL,
		  keychange_len	= SNMP_MAXBUF_SMALL;

	char      *s = NULL;
	u_char	  oldKu[SNMP_MAXBUF_SMALL],
		  newKu[SNMP_MAXBUF_SMALL],
		  oldkul[SNMP_MAXBUF_SMALL],
		  newkul[SNMP_MAXBUF_SMALL],
		  keychange[SNMP_MAXBUF_SMALL];

	int       i;
	int       arg = 1;

 	local_progname = argv[0];


 
	/*
	 * Parse.
	 */
	for(; (arg < argc) && (argv[arg][0] == '-') ; arg++){
		switch(argv[arg][1]){
		case 'D':  snmp_set_do_debugging(1);	break;
		case 'E':  engineid = (u_char *)argv[++arg];	break;
		case 'f':  forcepassphrase = 1;		break;
		case 'N':  newpass = argv[++arg];	break;
		case 'O':  oldpass = argv[++arg];	break;
		case 'P':  promptindicator = 0;		break;
		case 't':  transform_type_input = argv[++arg];	break;
		case 'v':  verbose = 1;			break;
		case 'V':  visible = 1;			break;
		case 'h':
			rval = 0;
		default:
			usage_to_file(stdout);
			exit(rval);
		}
	}

	if ( !transform_type_input ) {
		fprintf(stderr, "The -t option is mandatory.\n");
		usage_synopsis(stdout);
		exit(1000);
	}



	/*
	 * Convert and error check transform_type.
	 */
	if ( !strcmp(transform_type_input, "md5") ) {
		transform_type = usmHMACMD5AuthProtocol;

	} else if ( !strcmp(transform_type_input, "sha1") ) {
		transform_type = usmHMACSHA1AuthProtocol;

	} else {
		fprintf(stderr,
			"Unrecognized hash transform: \"%s\".\n",
			transform_type_input);
		usage_synopsis(stderr);
		QUITFUN(rval = SNMPERR_GENERR, main_quit);
	}

	if (verbose) {
		fprintf(stderr, "Hash:\t\t%s\n",
			(transform_type == usmHMACMD5AuthProtocol)
				? "usmHMACMD5AuthProtocol"
				: "usmHMACSHA1AuthProtocol"
			);
	}



	/* 
	 * Build engineID.  Accept hex engineID as the bits
	 * "in-and-of-themselves", otherwise create an engineID with the
	 * given string as text.
	 *
	 * If no engineID is given, lookup the first IP address for the
	 * localhost and use that (see setup_engineID()).
	 */
	if ( engineid && (tolower(*(engineid+1)) == 'x') ) {
		engineid_len = hex_to_binary2(	engineid+2,
						strlen((char *)engineid)-2,
						(char **) &engineid);
                DEBUGMSGTL(("encode_keychange","engineIDLen: %d\n", engineid_len));
	} else {
		engineid_len = setup_engineID(&engineid, (char *)engineid);

	} 

#ifdef SNMP_TESTING_CODE
	if (verbose) {
		fprintf(stderr, "EngineID:\t%s\n",
			/* XXX = */ dump_snmpEngineID(engineid, &engineid_len));
	}
#endif


	/*
	 * Get passphrases from user.
	 */
	rval = get_user_passphrases();
	QUITFUN(rval, main_quit);

	if ( strlen(oldpass) < USM_LENGTH_P_MIN ) {
		fprintf(stderr, "Old passphrase must be greater than %d "
				"characters in length.\n",
				USM_LENGTH_P_MIN);
		QUITFUN(rval = SNMPERR_GENERR, main_quit);

	} else if ( strlen(newpass) < USM_LENGTH_P_MIN ) {
		fprintf(stderr, "New passphrase must be greater than %d "
				"characters in length.\n",
				USM_LENGTH_P_MIN);
		QUITFUN(rval = SNMPERR_GENERR, main_quit);
	}

	if (verbose) {
		fprintf(stderr,
			"Old passphrase:\t%s\nNew passphrase:\t%s\n",
			oldpass, newpass);
	}



	/* 
	 * Compute Ku and Kul's from old and new passphrases, then
	 * compute the keychange string & print it out.
	 */
	rval = sc_init();
	QUITFUN(rval, main_quit);


	rval = generate_Ku(	transform_type, USM_LENGTH_OID_TRANSFORM,
				(u_char *)oldpass, strlen(oldpass),
				oldKu, &oldKu_len);
	QUITFUN(rval, main_quit);


	rval = generate_Ku(	transform_type, USM_LENGTH_OID_TRANSFORM,
				(u_char *)newpass, strlen(newpass),
				newKu, &newKu_len);
	QUITFUN(rval, main_quit);


        DEBUGMSGTL(("encode_keychange", "EID (%d): ", engineid_len));
        for(i=0; i < (int)engineid_len; i++)
          DEBUGMSGTL(("encode_keychange", "%02x",(int) (engineid[i])));
        DEBUGMSGTL(("encode_keychange","\n"));

        DEBUGMSGTL(("encode_keychange", "old Ku (%d) (from %s): ", oldKu_len, oldpass));
        for(i=0; i < (int)oldKu_len; i++)
          DEBUGMSGTL(("encode_keychange", "%02x",(int) (oldKu[i])));
        DEBUGMSGTL(("encode_keychange","\n"));

	rval = generate_kul(	transform_type, USM_LENGTH_OID_TRANSFORM,
				engineid, engineid_len,
				oldKu, oldKu_len,
				oldkul, &oldkul_len);
	QUITFUN(rval, main_quit);


        DEBUGMSGTL(("encode_keychange", "generating old Kul (%d) (from Ku): ", oldkul_len));
        for(i=0; i < (int)oldkul_len; i++)
          DEBUGMSGTL(("encode_keychange", "%02x",(int) (oldkul[i])));
        DEBUGMSGTL(("encode_keychange","\n"));

	rval = generate_kul(	transform_type, USM_LENGTH_OID_TRANSFORM,
				engineid, engineid_len,
				newKu, newKu_len,
				newkul, &newkul_len);
	QUITFUN(rval, main_quit);
        
        DEBUGMSGTL(("encode_keychange", "generating new Kul (%d) (from Ku): ", oldkul_len));
        for(i=0; i < (int)newkul_len; i++)
          DEBUGMSGTL(("encode_keychange", "%02x",newkul[i]));
        DEBUGMSGTL(("encode_keychange","\n"));

	rval = encode_keychange(transform_type, USM_LENGTH_OID_TRANSFORM,
				oldkul, oldkul_len,
				newkul, newkul_len,
				keychange, &keychange_len);
	QUITFUN(rval, main_quit);



	binary_to_hex(keychange, keychange_len, &s);
	printf("%s%s\n",
		(verbose) ? "KeyChange string:\t" : "", /* XXX stdout */
		s);


	/*
	 * Cleanup.
	 */
main_quit:
	snmp_call_callbacks(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN,
                            NULL);
        

	SNMP_ZERO(oldpass,	strlen(oldpass));
	SNMP_ZERO(newpass,	strlen(newpass));

	SNMP_ZERO(oldKu,	oldKu_len);
	SNMP_ZERO(newKu,	newKu_len);

	SNMP_ZERO(oldkul,	oldkul_len);
	SNMP_ZERO(newkul,	newkul_len);

	SNMP_ZERO(s, strlen(s));

	return rval;

} /* end main() */
Exemple #15
0
void
send_enterprise_trap_vars(int trap,
                          int specific,
                          oid * enterprise, int enterprise_length,
                          netsnmp_variable_list * vars)
{
    netsnmp_variable_list uptime_var, snmptrap_var, enterprise_var;
    netsnmp_variable_list *v2_vars, *last_var = NULL;
    netsnmp_pdu    *template_pdu;
    u_long          uptime;
    in_addr_t      *pdu_in_addr_t;
    struct trap_sink *sink;
#ifdef BRCM_SNMP_MIB_SUPPORT
    oid             temp_oid[MAX_OID_LEN];
#endif
    /*
     * Initialise SNMPv2 required variables
     */
    uptime = netsnmp_get_agent_uptime();
    memset(&uptime_var, 0, sizeof(netsnmp_variable_list));
    snmp_set_var_objid(&uptime_var, sysuptime_oid,
                       OID_LENGTH(sysuptime_oid));
    snmp_set_var_value(&uptime_var, (u_char *) & uptime, sizeof(uptime));
    uptime_var.type = ASN_TIMETICKS;
    uptime_var.next_variable = &snmptrap_var;

    memset(&snmptrap_var, 0, sizeof(netsnmp_variable_list));
    snmp_set_var_objid(&snmptrap_var, snmptrap_oid,
                       OID_LENGTH(snmptrap_oid));
    /*
     * value set later .... 
     */
    snmptrap_var.type = ASN_OBJECT_ID;
    if (vars)
        snmptrap_var.next_variable = vars;
    else
        snmptrap_var.next_variable = &enterprise_var;

    /*
     * find end of provided varbind list,
     * ready to append the enterprise info if necessary 
     */
    last_var = vars;
    while (last_var && last_var->next_variable)
        last_var = last_var->next_variable;

    memset(&enterprise_var, 0, sizeof(netsnmp_variable_list));
    snmp_set_var_objid(&enterprise_var,
                       snmptrapenterprise_oid,
                       OID_LENGTH(snmptrapenterprise_oid));
    snmp_set_var_value(&enterprise_var, (u_char *) enterprise,
                       enterprise_length * sizeof(oid));
    enterprise_var.type = ASN_OBJECT_ID;
    enterprise_var.next_variable = NULL;

    v2_vars = &uptime_var;

    /*
     *  Create a template PDU, ready for sending
     */
    template_pdu = snmp_pdu_create(SNMP_MSG_TRAP);
    if (template_pdu == NULL) {
        /*
         * Free memory if value stored dynamically 
         */
        snmp_set_var_value(&enterprise_var, NULL, 0);
        return;
    }
    template_pdu->trap_type = trap;
    template_pdu->specific_type = specific;
    if (snmp_clone_mem((void **) &template_pdu->enterprise,
                       enterprise, enterprise_length * sizeof(oid))) {
        snmp_free_pdu(template_pdu);
        snmp_set_var_value(&enterprise_var, NULL, 0);
        return;
    }
    template_pdu->enterprise_length = enterprise_length;
    template_pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY;

    pdu_in_addr_t = (in_addr_t *) template_pdu->agent_addr;
    *pdu_in_addr_t = get_myaddr();
    template_pdu->time = uptime;

    /*
     *  Now use the parameters to determine
     *    which v2 variables are needed,
     *    and what values they should take.
     */
    switch (trap) {
    case -1:                   /*
                                 *      SNMPv2 only
                                 *  Check to see whether the variables provided
                                 *    are sufficient for SNMPv2 notifications
                                 */
        if (vars && netsnmp_oid_equals(vars->name, vars->name_length,
                                     sysuptime_oid,
                                     OID_LENGTH(sysuptime_oid)) == 0)
            v2_vars = vars;
        else if (vars && netsnmp_oid_equals(vars->name, vars->name_length,
                                          snmptrap_oid,
                                          OID_LENGTH(snmptrap_oid)) == 0)
            uptime_var.next_variable = vars;
        else {
            /*
             * Hmmm... we don't seem to have a value - oops! 
             */
            snmptrap_var.next_variable = vars;
        }
        last_var = NULL;        /* Don't need enterprise info */
        convert_v2_to_v1(vars, template_pdu);
        break;

        /*
         * "Standard" SNMPv1 traps 
         */

    case SNMP_TRAP_COLDSTART:
        snmp_set_var_value(&snmptrap_var,
                           (u_char *) cold_start_oid,
                           sizeof(cold_start_oid));
        break;
    case SNMP_TRAP_WARMSTART:
        snmp_set_var_value(&snmptrap_var,
                           (u_char *) warm_start_oid,
                           sizeof(warm_start_oid));
        break;
    case SNMP_TRAP_LINKDOWN:
        snmp_set_var_value(&snmptrap_var,
                           (u_char *) link_down_oid,
                           sizeof(link_down_oid));
        break;
    case SNMP_TRAP_LINKUP:
        snmp_set_var_value(&snmptrap_var,
                           (u_char *) link_up_oid, sizeof(link_up_oid));
        break;
    case SNMP_TRAP_AUTHFAIL:
        if (snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) {
            snmp_free_pdu(template_pdu);
            snmp_set_var_value(&enterprise_var, NULL, 0);
            return;
        }
        snmp_set_var_value(&snmptrap_var,
                           (u_char *) auth_fail_oid,
                           sizeof(auth_fail_oid));
        break;
    case SNMP_TRAP_EGPNEIGHBORLOSS:
        snmp_set_var_value(&snmptrap_var,
                           (u_char *) egp_xxx_oid, sizeof(egp_xxx_oid));
        break;

#ifdef BRCM_SNMP_MIB_SUPPORT
    case SNMP_TRAP_ENTERPRISESPECIFIC:
        memcpy(temp_oid,
               (char *) enterprise, (enterprise_length) * sizeof(oid));
        temp_oid[enterprise_length] = 0;
        temp_oid[enterprise_length + 1] = specific;
        snmp_set_var_value(&snmptrap_var,
                           (u_char *) temp_oid,
                           (enterprise_length + 2) * sizeof(oid));
        snmptrap_var.next_variable = vars;
        last_var = NULL;        /* Don't need version info */
        break;
#endif /* BRCM_SNMP_MIB_SUPPORT */
    }


    /*
     *  Now loop through the list of trap sinks,
     *   sending an appropriately formatted PDU to each
     */
    for (sink = sinks; sink; sink = sink->next) {
        if (sink->version == SNMP_VERSION_1 && trap == -1)
            continue;           /* Skip v1 sinks for v2 only traps */
        template_pdu->command = sink->pdutype;

        if (sink->version != SNMP_VERSION_1) {
            template_pdu->variables = v2_vars;
            if (last_var)
                last_var->next_variable = &enterprise_var;
        } else
            template_pdu->variables = vars;

        send_trap_to_sess(sink->sesp, template_pdu);

        if (sink->version != SNMP_VERSION_1 && last_var)
            last_var->next_variable = NULL;
    }

    /*
     * send stuff to registered callbacks 
     */
    /*
     * v2 traps/informs 
     */
    template_pdu->variables = v2_vars;
    if (last_var)
        last_var->next_variable = &enterprise_var;

    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_SEND_TRAP2, template_pdu);

    if (last_var)
        last_var->next_variable = NULL;

    /*
     * v1 traps 
     */
    template_pdu->command = SNMP_MSG_TRAP;
    template_pdu->variables = vars;

    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_SEND_TRAP1, template_pdu);

    /*
     * Free memory if values stored dynamically 
     */
    snmp_set_var_value(&enterprise_var, NULL, 0);
    snmp_set_var_value(&snmptrap_var, NULL, 0);
    /*
     * Ensure we don't free anything we shouldn't 
     */
    if (last_var)
        last_var->next_variable = NULL;
    template_pdu->variables = NULL;
    snmp_free_pdu(template_pdu);
}
int
write_snmp(int action,
           u_char * var_val,
           u_char var_val_type,
           size_t var_val_len, u_char * statP, oid * name, size_t name_len)
{
    long            intval = 0;

    switch (action) {
    case RESERVE1:             /* Check values for acceptability */
        if (var_val_type != ASN_INTEGER) {
            DEBUGMSGTL(("mibII/snmp_mib", "%x not integer type",
                        var_val_type));
            return SNMP_ERR_WRONGTYPE;
        }

        intval = *((long *) var_val);
        if (intval != 1 && intval != 2) {
            DEBUGMSGTL(("mibII/snmp_mib", "not valid %x\n", intval));
            return SNMP_ERR_WRONGVALUE;
        }
        if (snmp_enableauthentrapsset < 0) {
            /*
             * The object is set in a read-only configuration file.  
             */
            return SNMP_ERR_NOTWRITABLE;
        }
        break;

    case RESERVE2:             /* Allocate memory and similar resources */

        /*
         * Using static variables, so nothing needs to be done 
         */
        break;

    case ACTION:               /* Perform the SET action (if reversible) */

        /*
         * Save the old value, in case of UNDO 
         */
        intval = *((long *) var_val);
        old_snmp_enableauthentraps = snmp_enableauthentraps;
        snmp_enableauthentraps = intval;
        break;

    case UNDO:                 /* Reverse the SET action and free resources */

        snmp_enableauthentraps = old_snmp_enableauthentraps;
        break;

    case COMMIT:
        snmp_enableauthentrapsset = 1;
        snmp_save_persistent(netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
        (void) snmp_call_callbacks(SNMP_CALLBACK_LIBRARY,
                                   SNMP_CALLBACK_STORE_DATA, NULL);
        snmp_clean_persistent(netsnmp_ds_get_string
                              (NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE));
        break;

    case FREE:                 /* Free any resources allocated */
        break;
    }
    return SNMP_ERR_NOERROR;
}
Exemple #17
0
/*
 * Open a session to the master agent.  
 */
int
subagent_open_master_session(void)
{
    netsnmp_session sess;

    DEBUGMSGTL(("agentx/subagent", "opening session...\n"));

    if (main_session) {
        snmp_log(LOG_WARNING,
                 "AgentX session to master agent attempted to be re-opened.");
        return -1;
    }

    snmp_sess_init(&sess);
    sess.version = AGENTX_VERSION_1;
    sess.retries = SNMP_DEFAULT_RETRIES;
    sess.timeout = SNMP_DEFAULT_TIMEOUT;
    sess.flags |= SNMP_FLAGS_STREAM_SOCKET;
    if (netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET)) {
        sess.peername =
            netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET);
    } else {
        sess.peername = strdup(AGENTX_SOCKET);
    }

    sess.local_port = 0;        /* client */
    sess.remote_port = AGENTX_PORT;     /* default port */
    sess.callback = handle_agentx_packet;
    sess.authenticator = NULL;
    main_session = snmp_open_ex(&sess, NULL, agentx_parse, NULL, NULL,
                                agentx_realloc_build, agentx_check_packet);

    if (main_session == NULL) {
        /*
         * Diagnose snmp_open errors with the input
         * netsnmp_session pointer.  
         */
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) {
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                netsnmp_sess_log_error(LOG_WARNING,
                                       "Error: Failed to connect to the agentx master agent",
                                       &sess);
            } else {
                snmp_sess_perror
                    ("Error: Failed to connect to the agentx master agent",
                     &sess);
            }
        }
        return -1;
    }

    if (agentx_open_session(main_session) < 0) {
        snmp_close(main_session);
        main_session = NULL;
        return -1;
    }

    if (add_trap_session(main_session, AGENTX_MSG_NOTIFY, 1,
                         AGENTX_VERSION_1)) {
        DEBUGMSGTL(("agentx/subagent", " trap session registered OK\n"));
    } else {
        DEBUGMSGTL(("agentx/subagent",
                    "trap session registration failed\n"));
        snmp_close(main_session);
        main_session = NULL;
        return -1;
    }

    agentx_register_callbacks(main_session);

    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_INDEX_START, (void *) main_session);

    DEBUGMSGTL(("agentx/subagent", "opening session...  DONE (%p)\n",
                main_session));

    return 0;
}
Exemple #18
0
int
unregister_mib_range( oid *name, size_t len, int priority,
	     		int range_subid, oid range_ubound)
{
  struct subtree *list, *myptr;
  struct subtree *prev, *child;             /* loop through children */
  struct register_parameters reg_parms;

  list = find_subtree( name, len, subtrees );
  if ( list == NULL )
	return MIB_NO_SUCH_REGISTRATION;

  for ( child=list, prev=NULL;  child != NULL;
			 	prev=child, child=child->children ) {
      if (( snmp_oid_compare( child->name, child->namelen, name, len) == 0 )
	  && ( child->priority == priority ))
		break;	/* found it */
  }
  if ( child == NULL )
	return MIB_NO_SUCH_REGISTRATION;

  unload_subtree( child, prev );
  myptr = child;	/* remember this for later */

		/*
		 *  Now handle any occurances in the following subtrees,
		 *	as a result of splitting this range.  Due to the
		 *	nature of the way such splits work, the first
		 * 	subtree 'slice' that doesn't refer to the given
		 *	name marks the end of the original region.
		 *
		 *  This should also serve to register ranges.
		 */

  for ( list = myptr->next ; list != NULL ; list=list->next ) {
  	for ( child=list, prev=NULL;  child != NULL;
			 	      prev=child, child=child->children ) {
	    if (( snmp_oid_compare( child->name, child->namelen,
							name, len) == 0 )
		&& ( child->priority == priority )) {

		    unload_subtree( child, prev );
		    free_subtree( child );
		    break;
	    }
	}
	if ( child == NULL )	/* Didn't find the given name */
	    break;
  }
  free_subtree( myptr );
  
  reg_parms.name = name;
  reg_parms.namelen = len;
  reg_parms.priority = priority;
  reg_parms.range_subid  = range_subid;
  reg_parms.range_ubound = range_ubound;
  snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_UNREGISTER_OID,
                      &reg_parms);

  return MIB_UNREGISTERED_OK;
}
Exemple #19
0
int
register_mib_range(const char *moduleName,
	     struct variable *var,
	     size_t varsize,
	     size_t numvars,
	     oid *mibloc,
	     size_t mibloclen,
	     int priority,
	     int range_subid,
	     oid range_ubound,
	     struct snmp_session *ss)
{
  struct subtree *subtree, *sub2;
  int res, i;
  struct register_parameters reg_parms;
  
  subtree = (struct subtree *) malloc(sizeof(struct subtree));
  if ( subtree == NULL )
    return MIB_REGISTRATION_FAILED;
  memset(subtree, 0, sizeof(struct subtree));

  DEBUGMSGTL(("register_mib", "registering \"%s\" at ", moduleName));
  DEBUGMSGOID(("register_mib", mibloc, mibloclen));
  DEBUGMSG(("register_mib","\n"));
    
	/*
	 * Create the new subtree node being registered
	 */
  memcpy(subtree->name, mibloc, mibloclen*sizeof(oid));
  subtree->namelen = (u_char) mibloclen;
  memcpy(subtree->start, mibloc, mibloclen*sizeof(oid));
  subtree->start_len = (u_char) mibloclen;
  memcpy(subtree->end, mibloc, mibloclen*sizeof(oid));
  subtree->end[ mibloclen-1 ]++;	/* XXX - or use 'variables' info ? */
  subtree->end_len = (u_char) mibloclen;
  memcpy(subtree->label, moduleName, strlen(moduleName)+1);
  if ( var ) {
    subtree->variables = (struct variable *) malloc(varsize*numvars);
    memcpy(subtree->variables, var, numvars*varsize);
    subtree->variables_len = numvars;
    subtree->variables_width = varsize;
  }
  subtree->priority = priority;
  subtree->session = ss;
  res = load_subtree(subtree);

	/*
	 * If registering a range,
	 *   use the first subtree as a template
	 *   for the rest of the range
	 */
  if (( res == MIB_REGISTERED_OK ) && ( range_subid != 0 )) {
    for ( i = mibloc[range_subid-1] +1 ; i < (int)range_ubound ; i++ ) {
	sub2 = (struct subtree *) malloc(sizeof(struct subtree));
	if ( sub2 == NULL ) {
	    unregister_mib_range( mibloc, mibloclen, priority,
				  range_subid, range_ubound);
	    return MIB_REGISTRATION_FAILED;
	}
	memcpy( sub2, subtree, sizeof(struct subtree));
	sub2->start[range_subid-1] = i;
	sub2->end[  range_subid-1] = i;		/* XXX - ???? */
	res = load_subtree(sub2);
	if ( res != MIB_REGISTERED_OK ) {
	    unregister_mib_range( mibloc, mibloclen, priority,
				  range_subid, range_ubound);
	    return MIB_REGISTRATION_FAILED;
	}
    }
  }


  reg_parms.name = mibloc;
  reg_parms.namelen = mibloclen;
  reg_parms.priority = priority;
  reg_parms.range_subid  = range_subid;
  reg_parms.range_ubound = range_ubound;
  snmp_call_callbacks(SNMP_CALLBACK_APPLICATION, SNMPD_CALLBACK_REGISTER_OID,
                      &reg_parms);

  return res;
}
Exemple #20
0
/**
 * This function allows you to make a distinction between generic 
 * traps from different classes of equipment. For example, you may want 
 * to handle a SNMP_TRAP_LINKDOWN trap for a particular device in a 
 * different manner to a generic system SNMP_TRAP_LINKDOWN trap.
 *   
 *
 * @param trap is the generic trap type.  The trap types are:
 *		- SNMP_TRAP_COLDSTART:
 *			cold start
 *		- SNMP_TRAP_WARMSTART:
 *			warm start
 *		- SNMP_TRAP_LINKDOWN:
 *			link down
 *		- SNMP_TRAP_LINKUP:
 *			link up
 *		- SNMP_TRAP_AUTHFAIL:
 *			authentication failure
 *		- SNMP_TRAP_EGPNEIGHBORLOSS:
 *			egp neighbor loss
 *		- SNMP_TRAP_ENTERPRISESPECIFIC:
 *			enterprise specific
 *			
 * @param specific is the specific trap value.
 *
 * @param enterprise is an enterprise oid in which you want to send specifc 
 *	traps from. 
 *
 * @param enterprise_length is the length of the enterprise oid, use macro,
 *	OID_LENGTH, to compute length.
 *
 * @param vars is used to supply list of variable bindings to form an SNMPv2 
 *	trap.
 *
 * @param context currently unused 
 *
 * @param flags currently unused 
 *
 * @return void
 *
 * @see send_easy_trap
 * @see send_v2trap
 */
int
netsnmp_send_traps(int trap, int specific,
                          oid * enterprise, int enterprise_length,
                          netsnmp_variable_list * vars,
                          char * context, int flags)
{
    netsnmp_pdu           *template_v1pdu;
    netsnmp_pdu           *template_v2pdu;
    netsnmp_variable_list *vblist = NULL;
    netsnmp_variable_list *trap_vb;
    netsnmp_variable_list *var;
    in_addr_t             *pdu_in_addr_t;
    u_long                 uptime;
    struct trap_sink *sink;

    DEBUGMSGTL(( "trap", "send_trap %d %d ", trap, specific));
    DEBUGMSGOID(("trap", enterprise, enterprise_length));
    DEBUGMSG(( "trap", "\n"));

    if (vars) {
        vblist = snmp_clone_varbind( vars );
        if (!vblist) {
            snmp_log(LOG_WARNING,
                     "send_trap: failed to clone varbind list\n");
            return -1;
        }
    }

    if ( trap == -1 ) {
        /*
         * Construct the SNMPv2-style notification PDU
         */
        if (!vblist) {
            snmp_log(LOG_WARNING,
                     "send_trap: called with NULL v2 information\n");
            return -1;
        }
        template_v2pdu = snmp_pdu_create(SNMP_MSG_TRAP2);
        if (!template_v2pdu) {
            snmp_log(LOG_WARNING,
                     "send_trap: failed to construct v2 template PDU\n");
            snmp_free_varbind(vblist);
            return -1;
        }

        /*
         * Check the varbind list we've been given.
         * If it starts with a 'sysUptime.0' varbind, then use that.
         * Otherwise, prepend a suitable 'sysUptime.0' varbind.
         */
        if (!snmp_oid_compare( vblist->name,    vblist->name_length,
                               sysuptime_oid, sysuptime_oid_len )) {
            template_v2pdu->variables = vblist;
            trap_vb  = vblist->next_variable;
        } else {
            uptime   = netsnmp_get_agent_uptime();
            var = NULL;
            snmp_varlist_add_variable( &var,
                           sysuptime_oid, sysuptime_oid_len,
                           ASN_TIMETICKS, (u_char*)&uptime, sizeof(uptime));
            if (!var) {
                snmp_log(LOG_WARNING,
                     "send_trap: failed to insert sysUptime varbind\n");
                snmp_free_pdu(template_v2pdu);
                snmp_free_varbind(vblist);
                return -1;
            }
            template_v2pdu->variables = var;
            var->next_variable        = vblist;
            trap_vb  = vblist;
        }

        /*
         * 'trap_vb' should point to the snmpTrapOID.0 varbind,
         *   identifying the requested trap.  If not then bomb out.
         * If it's a 'standard' trap, then we need to append an
         *   snmpEnterprise varbind (if there isn't already one).
         */
        if (!trap_vb ||
            snmp_oid_compare(trap_vb->name, trap_vb->name_length,
                             snmptrap_oid,  snmptrap_oid_len)) {
            snmp_log(LOG_WARNING,
                     "send_trap: no v2 trapOID varbind provided\n");
            snmp_free_pdu(template_v2pdu);
            return -1;
        }
        if (!snmp_oid_compare(vblist->val.objid, OID_LENGTH(trap_prefix),
                              trap_prefix,       OID_LENGTH(trap_prefix))) {
            var = find_varbind_in_list( template_v2pdu->variables,
                                        snmptrapenterprise_oid,
                                        snmptrapenterprise_oid_len);
            if (!var &&
                !snmp_varlist_add_variable( &(template_v2pdu->variables),
                     snmptrapenterprise_oid, snmptrapenterprise_oid_len,
                     ASN_OBJECT_ID,
                     (char*)enterprise, enterprise_length*sizeof(oid))) {
                snmp_log(LOG_WARNING,
                     "send_trap: failed to add snmpEnterprise to v2 trap\n");
                snmp_free_pdu(template_v2pdu);
                return -1;
            }
        }
            

        /*
         * If everything's OK, convert the v2 template into an SNMPv1 trap PDU.
         */
        template_v1pdu = convert_v2pdu_to_v1( template_v2pdu );
        if (!template_v1pdu) {
            snmp_log(LOG_WARNING,
                     "send_trap: failed to convert v2->v1 template PDU\n");
        }

    } else {
        /*
         * Construct the SNMPv1 trap PDU....
         */
        template_v1pdu = snmp_pdu_create(SNMP_MSG_TRAP);
        if (!template_v1pdu) {
            snmp_log(LOG_WARNING,
                     "send_trap: failed to construct v1 template PDU\n");
            snmp_free_varbind(vblist);
            return -1;
        }
        template_v1pdu->trap_type     = trap;
        template_v1pdu->specific_type = specific;
        template_v1pdu->time          = netsnmp_get_agent_uptime();

        if (snmp_clone_mem((void **) &template_v1pdu->enterprise,
                       enterprise, enterprise_length * sizeof(oid))) {
            snmp_log(LOG_WARNING,
                     "send_trap: failed to set v1 enterprise OID\n");
            snmp_free_varbind(vblist);
            snmp_free_pdu(template_v1pdu);
            return -1;
        }
        template_v1pdu->enterprise_length = enterprise_length;

        template_v1pdu->flags    |= UCD_MSG_FLAG_FORCE_PDU_COPY;
        template_v1pdu->variables = vblist;

        /*
         * ... and convert it into an SNMPv2-style notification PDU.
         */

        template_v2pdu = convert_v1pdu_to_v2( template_v1pdu );
        if (!template_v2pdu) {
            snmp_log(LOG_WARNING,
                     "send_trap: failed to convert v1->v2 template PDU\n");
        }
    }

    /*
     * Check whether we're ignoring authFail traps
     */
    if (template_v1pdu) {
      if (template_v1pdu->trap_type == SNMP_TRAP_AUTHFAIL &&
        snmp_enableauthentraps == SNMP_AUTHENTICATED_TRAPS_DISABLED) {
        snmp_free_pdu(template_v1pdu);
        snmp_free_pdu(template_v2pdu);
        return 0;
      }

    /*
     * Ensure that the v1 trap PDU includes the local IP address
     */
       pdu_in_addr_t = (in_addr_t *) template_v1pdu->agent_addr;
      *pdu_in_addr_t = get_myaddr();
    }


    /*
     *  Now loop through the list of trap sinks
     *   and call the trap callback routines,
     *   providing an appropriately formatted PDU in each case
     */
    for (sink = sinks; sink; sink = sink->next) {
#ifndef NETSNMP_DISABLE_SNMPV1
        if (sink->version == SNMP_VERSION_1) {
          if (template_v1pdu) {
            send_trap_to_sess(sink->sesp, template_v1pdu);
          }
        } else {
#endif
          if (template_v2pdu) {
            template_v2pdu->command = sink->pdutype;
            send_trap_to_sess(sink->sesp, template_v2pdu);
          }
#ifndef NETSNMP_DISABLE_SNMPV1
        }
#endif
    }
    if (template_v1pdu)
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_SEND_TRAP1, template_v1pdu);
    if (template_v2pdu)
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_SEND_TRAP2, template_v2pdu);
    snmp_free_pdu(template_v1pdu);
    snmp_free_pdu(template_v2pdu);
    return 0;
}
Exemple #21
0
/** registers a row within a mib table */
int
netsnmp_register_mib_table_row(const char *moduleName,
                               struct variable *var,
                               size_t varsize,
                               size_t numvars,
                               oid * mibloc,
                               size_t mibloclen,
                               int priority,
                               int var_subid,
                               netsnmp_session * ss,
                               const char *context, int timeout, int flags)
{
    unsigned int    i = 0, rc = 0;
    oid             ubound = 0;

    for (i = 0; i < numvars; i++) {
        struct variable *vr =
            (struct variable *) ((char *) var + (i * varsize));
        netsnmp_handler_registration *r;
        if ( var_subid > (int)mibloclen ) {
            break;    /* doesn't make sense */
        }
        r = SNMP_MALLOC_TYPEDEF(netsnmp_handler_registration);

        if (r == NULL) {
            /*
             * Unregister whatever we have registered so far, and
             * return an error.  
             */
            rc = MIB_REGISTRATION_FAILED;
            break;
        }
        memset(r, 0, sizeof(netsnmp_handler_registration));

        r->handler = get_old_api_handler();
        r->handlerName = strdup(moduleName);

        if (r->handlerName == NULL) {
            netsnmp_handler_registration_free(r);
            break;
        }

        r->rootoid_len = mibloclen;
        r->rootoid = (oid *) malloc(r->rootoid_len * sizeof(oid));

        if (r->rootoid == NULL) {
            netsnmp_handler_registration_free(r);
            rc = MIB_REGISTRATION_FAILED;
            break;
        }
        memcpy(r->rootoid, mibloc, mibloclen * sizeof(oid));
        memcpy((u_char *) (r->rootoid + (var_subid - vr->namelen)), vr->name,
               vr->namelen * sizeof(oid));
        DEBUGMSGTL(("netsnmp_register_mib_table_row", "rootoid "));
        DEBUGMSGOID(("netsnmp_register_mib_table_row", r->rootoid,
                     r->rootoid_len));
        DEBUGMSG(("netsnmp_register_mib_table_row", "(%d)\n",
                     (var_subid - vr->namelen)));
        r->handler->myvoid = netsnmp_duplicate_variable(vr);
        r->handler->data_clone = (void *(*)(void *))netsnmp_duplicate_variable;
        r->handler->data_free = free;

        if (r->handler->myvoid == NULL) {
            netsnmp_handler_registration_free(r);
            rc = MIB_REGISTRATION_FAILED;
            break;
        }

        r->contextName = (context) ? strdup(context) : NULL;

        if (context != NULL && r->contextName == NULL) {
            netsnmp_handler_registration_free(r);
            rc = MIB_REGISTRATION_FAILED;
            break;
        }

        r->priority = priority;
        r->range_subid = 0;     /* var_subid; */
        r->range_ubound = 0;    /* range_ubound; */
        r->timeout = timeout;
        r->modes = HANDLER_CAN_RWRITE;

        /*
         * Register this column and row  
         */
        if ((rc =
             netsnmp_register_handler_nocallback(r)) !=
            MIB_REGISTERED_OK) {
            DEBUGMSGTL(("netsnmp_register_mib_table_row",
                        "register failed %d\n", rc));
            netsnmp_handler_registration_free(r);
            break;
        }

        if (vr->namelen > 0) {
            if (vr->name[vr->namelen - 1] > ubound) {
                ubound = vr->name[vr->namelen - 1];
            }
        }
    }

    if (rc == MIB_REGISTERED_OK) {
        struct register_parameters reg_parms;

        reg_parms.name = mibloc;
        reg_parms.namelen = mibloclen;
        reg_parms.priority = priority;
        reg_parms.flags = (u_char) flags;
        reg_parms.range_subid = var_subid;
        reg_parms.range_ubound = ubound;
        reg_parms.timeout = timeout;
        reg_parms.contextName = context;
        rc = snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                                 SNMPD_CALLBACK_REGISTER_OID, &reg_parms);
    }

    return rc;
}
int
handle_agentx_packet(int operation, netsnmp_session * session, int reqid,
                     netsnmp_pdu *pdu, void *magic)
{
    struct agent_netsnmp_set_info *asi = NULL;
    snmp_callback   mycallback;
    netsnmp_pdu    *internal_pdu = NULL;
    void           *retmagic = NULL;
    ns_subagent_magic *smagic = NULL;

    if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) {
        struct synch_state *state = (struct synch_state *) magic;
        int             period =
            netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID,
                               NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL);
        DEBUGMSGTL(("agentx/subagent",
                    "transport disconnect indication\n"));

        /*
         * deal with existing session. This happend if agentx sends
         * a message to the master, but the master goes away before
         * a response is sent. agentx will spin in snmp_synch_response_cb,
         * waiting for a response. At the very least, the waiting
         * flag must be set to break that loop. The rest is copied
         * from disconnect handling in snmp_sync_input.
         */
        if(state) {
            state->waiting = 0;
            state->pdu = NULL;
            state->status = STAT_ERROR;
            session->s_snmp_errno = SNMPERR_ABORT;
            SET_SNMP_ERROR(SNMPERR_ABORT);
        }

        /*
         * Deregister the ping alarm, if any, and invalidate all other
         * references to this session.  
         */
        if (session->securityModel != SNMP_DEFAULT_SECMODEL) {
            snmp_alarm_unregister(session->securityModel);
        }
        snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                            SNMPD_CALLBACK_INDEX_STOP, (void *) session);
        agentx_unregister_callbacks(session);
        remove_trap_session(session);
        register_mib_detach();
        main_session = NULL;
        if (period != 0) {
            /*
             * Pings are enabled, so periodically attempt to re-establish contact 
             * with the master agent.  Don't worry about the handle,
             * agentx_reopen_session unregisters itself if it succeeds in talking 
             * to the master agent.  
             */
            snmp_alarm_register(period, SA_REPEAT, agentx_reopen_session,
                                NULL);
        }
        return 0;
    } else if (operation != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
        DEBUGMSGTL(("agentx/subagent", "unexpected callback op %d\n",
                    operation));
        return 1;
    }

    /*
     * ok, we have a pdu from the net. Modify as needed 
     */

    DEBUGMSGTL(("agentx/subagent", "handling agentx request (req=0x%x,trans="
                "0x%x,sess=0x%x)\n", pdu->reqid,pdu->transid, pdu->sessid));
    pdu->version = AGENTX_VERSION_1;
    pdu->flags |= UCD_MSG_FLAG_ALWAYS_IN_VIEW;

    if (pdu->command == AGENTX_MSG_GET
        || pdu->command == AGENTX_MSG_GETNEXT
        || pdu->command == AGENTX_MSG_GETBULK) {
        smagic =
            (ns_subagent_magic *) calloc(1, sizeof(ns_subagent_magic));
        if (smagic == NULL) {
            DEBUGMSGTL(("agentx/subagent", "couldn't malloc() smagic\n"));
            return 1;
        }
        smagic->original_command = pdu->command;
        smagic->session = session;
        smagic->ovars = NULL;
        retmagic = (void *) smagic;
    }

    switch (pdu->command) {
    case AGENTX_MSG_GET:
        DEBUGMSGTL(("agentx/subagent", "  -> get\n"));
        pdu->command = SNMP_MSG_GET;
        mycallback = handle_subagent_response;
        break;

    case AGENTX_MSG_GETNEXT:
        DEBUGMSGTL(("agentx/subagent", "  -> getnext\n"));
        pdu->command = SNMP_MSG_GETNEXT;

        /*
         * We have to save a copy of the original variable list here because
         * if the master agent has requested scoping for some of the varbinds
         * that information is stored there.  
         */

        smagic->ovars = snmp_clone_varbind(pdu->variables);
        DEBUGMSGTL(("agentx/subagent", "saved variables\n"));
        mycallback = handle_subagent_response;
        break;

    case AGENTX_MSG_GETBULK:
        /*
         * WWWXXX 
         */
        DEBUGMSGTL(("agentx/subagent", "  -> getbulk\n"));
        pdu->command = SNMP_MSG_GETBULK;

        /*
         * We have to save a copy of the original variable list here because
         * if the master agent has requested scoping for some of the varbinds
         * that information is stored there.  
         */

        smagic->ovars = snmp_clone_varbind(pdu->variables);
        DEBUGMSGTL(("agentx/subagent", "saved variables at %p\n",
                    smagic->ovars));
        mycallback = handle_subagent_response;
        break;

    case AGENTX_MSG_RESPONSE:
        SNMP_FREE(smagic);
        DEBUGMSGTL(("agentx/subagent", "  -> response\n"));
        return 1;

    case AGENTX_MSG_TESTSET:
        /*
         * XXXWWW we have to map this twice to both RESERVE1 and RESERVE2 
         */
        DEBUGMSGTL(("agentx/subagent", "  -> testset\n"));
        asi = save_set_vars(session, pdu);
        if (asi == NULL) {
            SNMP_FREE(smagic);
            snmp_log(LOG_WARNING, "save_set_vars() failed\n");
            return 1;
        }
        asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_RESERVE1;
        mycallback = handle_subagent_set_response;
        retmagic = asi;
        break;

    case AGENTX_MSG_COMMITSET:
        DEBUGMSGTL(("agentx/subagent", "  -> commitset\n"));
        asi = restore_set_vars(session, pdu);
        if (asi == NULL) {
            SNMP_FREE(smagic);
            snmp_log(LOG_WARNING, "restore_set_vars() failed\n");
            return 1;
        }
        if (asi->mode != SNMP_MSG_INTERNAL_SET_RESERVE2) {
            SNMP_FREE(smagic);
            snmp_log(LOG_WARNING,
                     "dropping bad AgentX request (wrong mode %d)\n",
                     asi->mode);
            return 1;
        }
        asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_ACTION;
        mycallback = handle_subagent_set_response;
        retmagic = asi;
        break;

    case AGENTX_MSG_CLEANUPSET:
        DEBUGMSGTL(("agentx/subagent", "  -> cleanupset\n"));
        asi = restore_set_vars(session, pdu);
        if (asi == NULL) {
            SNMP_FREE(smagic);
            snmp_log(LOG_WARNING, "restore_set_vars() failed\n");
            return 1;
        }
        if (asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE1 ||
            asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE2) {
            asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_FREE;
        } else if (asi->mode == SNMP_MSG_INTERNAL_SET_ACTION) {
            asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_COMMIT;
        } else {
            snmp_log(LOG_WARNING,
                     "dropping bad AgentX request (wrong mode %d)\n",
                     asi->mode);
            SNMP_FREE(retmagic);
            return 1;
        }
        mycallback = handle_subagent_set_response;
        retmagic = asi;
        break;

    case AGENTX_MSG_UNDOSET:
        DEBUGMSGTL(("agentx/subagent", "  -> undoset\n"));
        asi = restore_set_vars(session, pdu);
        if (asi == NULL) {
            SNMP_FREE(smagic);
            snmp_log(LOG_WARNING, "restore_set_vars() failed\n");
            return 1;
        }
        asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_UNDO;
        mycallback = handle_subagent_set_response;
        retmagic = asi;
        break;

    default:
        SNMP_FREE(smagic);
        DEBUGMSGTL(("agentx/subagent", "  -> unknown command %d (%02x)\n",
                    pdu->command, pdu->command));
        return 0;
    }

    /*
     * submit the pdu to the internal handler 
     */

    /*
     * We have to clone the PDU here, because when we return from this
     * callback, sess_process_packet will free(pdu), but this call also
     * free()s its argument PDU.  
     */

    internal_pdu = snmp_clone_pdu(pdu);
    internal_pdu->contextName = internal_pdu->community;
    internal_pdu->contextNameLen = internal_pdu->community_len;
    internal_pdu->community = NULL;
    internal_pdu->community_len = 0;
    snmp_async_send(agentx_callback_sess, internal_pdu, mycallback,
                    retmagic);
    return 1;
}
/*
 * Open a session to the master agent.  
 */
int
subagent_open_master_session(void)
{
    netsnmp_transport *t;
    netsnmp_session sess;

    DEBUGMSGTL(("agentx/subagent", "opening session...\n"));

    if (main_session) {
        snmp_log(LOG_WARNING,
                 "AgentX session to master agent attempted to be re-opened.");
        return -1;
    }

    snmp_sess_init(&sess);
    sess.version = AGENTX_VERSION_1;
    sess.retries = SNMP_DEFAULT_RETRIES;
    sess.timeout = SNMP_DEFAULT_TIMEOUT;
    sess.flags |= SNMP_FLAGS_STREAM_SOCKET;
    sess.callback = handle_agentx_packet;
    sess.authenticator = NULL;

    t = netsnmp_transport_open_client(
            "agentx", netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                            NETSNMP_DS_AGENT_X_SOCKET));
    if (t == NULL) {
        /*
         * Diagnose snmp_open errors with the input
         * netsnmp_session pointer.  
         */
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                    NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) {
            char buf[1024];
            const char *socket =
                netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                      NETSNMP_DS_AGENT_X_SOCKET);
            snprintf(buf, sizeof(buf), "Warning: "
                     "Failed to connect to the agentx master agent (%s)",
                     socket ? socket : "[NIL]");
            if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                        NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
                netsnmp_sess_log_error(LOG_WARNING, buf, &sess);
            } else {
                snmp_sess_perror(buf, &sess);
            }
        }
        return -1;
    }

    main_session =
        snmp_add_full(&sess, t, NULL, agentx_parse, NULL, NULL,
                      agentx_realloc_build, agentx_check_packet, NULL);

    if (main_session == NULL) {
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                    NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) {
            char buf[1024];
            snprintf(buf, sizeof(buf), "Error: "
                     "Failed to create the agentx master agent session (%s)",
                     netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID,
                                           NETSNMP_DS_AGENT_X_SOCKET));
            snmp_sess_perror(buf, &sess);
        }
        netsnmp_transport_free(t);
        return -1;
    }

    /*
     * I don't know why 1 is success instead of the usual 0 = noerr, 
     * but that's what the function returns.
     */
    if (1 != agentx_open_session(main_session)) {
        snmp_close(main_session);
        main_session = NULL;
        return -1;
    }

    if (add_trap_session(main_session, AGENTX_MSG_NOTIFY, 1,
                         AGENTX_VERSION_1)) {
        DEBUGMSGTL(("agentx/subagent", " trap session registered OK\n"));
    } else {
        DEBUGMSGTL(("agentx/subagent",
                    "trap session registration failed\n"));
        snmp_close(main_session);
        main_session = NULL;
        return -1;
    }

    agentx_register_callbacks(main_session);

    snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
                        SNMPD_CALLBACK_INDEX_START, (void *) main_session);

    snmp_log(LOG_INFO, "NET-SNMP version %s AgentX subagent connected\n",
             netsnmp_get_version());
    DEBUGMSGTL(("agentx/subagent", "opening session...  DONE (%p)\n",
                main_session));

    return 0;
}