On Tue, Feb 08, 2022 at 02:28:57PM +0000, Winston Gadsby wrote:
> It turns out I never did have it working.  I'm trying to reregister 
> sysContact and/or sysLocation from my subagent running under a master agent.  
> I think reregistering a system oid via a subagent is impossible.

It is quite possible.

You should just set the priority.

The attached files can be compiled using

gcc netsnmptmp.348085.c sysContact.c -o sysContact -lnetsnmpagent -lnetsnmp

and then run like

./sysContact -f -Lo -Dagentx

(the arguments are just to make it run in the foreground and log agentx
 interactions)

The important part - as I said last week - is to use a lower priority than
the one the agent uses so the magic line is sysContact.c:27.

/MF

> I set up a sample subagent project in c as described here:  
> http://www.net-snmp.org/wiki/index.php/TUT:Writing_a_Subagent.  I set up 
> debugging.  When I try to unregister an object using unregister_mib(), it 
> eventually calls unregister_mib_context() with null context, which calls 
> netsnmp_subtree_find().  This returns a subtree with a single oid {1,}, or 
> this plus a subtree consisting of the newly registered element in the sample 
> code, if I register the sample element first.  It tries to find the 
> sysLocation node to unregister in this tree, which fails, since the returned 
> tree only consists of objects I've registered in the subagent.  If I replace 
> sysLocation with nstAgentSubagentObject (the newly registered element from 
> the example code) it does successfully unregister.
> 
> I turned on debugging in snmpd for register_mib, to verify that sysLocation 
> and sysContact are being registered in null context by the master agentx:
> 
> register_mib:
> Feb 08 09:01:25 emma snmpd[169114]: registering "mibII/sysLocation" at
> Feb 08 09:01:25 emma snmpd[169114]: iso.3.6.1.2.1.1.6
> Feb 08 09:01:25 emma snmpd[169114]:  with context "(null)"
> 
> I don't think it's possible to unregister or reregister sysLocation or 
> sysContact from a subagent, if the node was initially registered in the 
> master agentx.
> 
>      Winston
> 
> 
> 
> 
> ________________________________
> From: Winston Gadsby <wgad...@enginuitycom.com>
> Sent: Wednesday, February 2, 2022 1:29 PM
> To: Magnus Fromreide <ma...@lysator.liu.se>
> Cc: Larry Hayes <lhay...@gmail.com>; net-snmp-coders@lists.sourceforge.net 
> <net-snmp-coders@lists.sourceforge.net>
> Subject: Re: Re-registering sysContact and sysLocation with subagent
> 
> You're right.  It looks like it's expecting an unsigned long array (c_oid_p 
> in the python wrapper).  Here's what I did in python.  First, I defined the 
> unregister_mib arguments for the ctypes translation:
> 
> $ libnsa.unregister_mib.argtypes = [c_oid_p, ctypes.c_size_t]
> $ libnsa.unregister_mib.restype = ctypes.c_int
> 
> Then I defined the oid vars:
> 
> $ oid = (c_oid * MAX_OID_LEN)()
> $ oid_len = ctypes.c_size_t(MAX_OID_LEN)
> 
> c_oid is the ctypes definition for oid, ctypes.c_ulong.  Then c_oid_p is a 
> pointer to it.  Then I used read_objid to translate from the text to the 
> unsigned long format:
> 
> $ libnsa.read_objid(b"SNMPv2-MIB::sysContact", ctypes.cast(ctypes.byref(oid), 
> c_oid_p), ctypes.byref(oid_len))
> 
> The result looks correct:  [1, 3, 6, 1, 2, 1, 1, 4, ...].  Then I used this 
> oid and oid_len in unregister_mib, translating the args appropriately:
> 
> $ result = libnsa.unregister_mib(ctypes.cast(ctypes.byref(oid), c_oid_p), 
> oid_len)
> 
> The result is still always -1 (MIB_NOSUCHREGISTRATION).  However, it looks 
> like it works, at least for sysContact.  If I ignore the error and reregister 
> sysContact with my subagent it works.  I can change it in my program and see 
> the change in a mib browser.
> 
> The very strange thing is I'm doing this with two separate, similar variables 
> - sysContact and sysLocation.  SysContact always works, with the exception of 
> the above error.  SysLocation always gives me another error when I start the 
> agent:  registering pdu failed 263, and I am unable to change its value in my 
> application.  When I started all this, and didn't do any unregister_mib 
> calls, I'd get two of the "registering pdu failed 263" errors, I'm assuming 
> one for sysContact and one for sysLocation.  So it looks like sysContact is 
> now working, but sysLocation is still registered with the master agent.  I'm 
> tracing this out and hoping it is a simple typo somewhere with sysLocation.
> 
> What type of agentx library did you have in mind?
> 
> Thanks again.
> 
>      Winston
> 
> 
> 
> 
> ________________________________
> From: Magnus Fromreide <ma...@lysator.liu.se>
> Sent: Tuesday, February 1, 2022 8:56 PM
> To: Winston Gadsby <wgad...@enginuitycom.com>
> Cc: Larry Hayes <lhay...@gmail.com>; net-snmp-coders@lists.sourceforge.net 
> <net-snmp-coders@lists.sourceforge.net>
> Subject: Re: Re-registering sysContact and sysLocation with subagent
> 
> On Tue, Feb 01, 2022 at 02:58:14PM +0000, Winston Gadsby wrote:
> > Hi,
> > Thanks for the replies.  I'm working on trying to unregister the oid 
> > according to the link given below, using unregister_mib(oid, len).  I'm 
> > assuming the oid can be specified as a byte-string or integer array.  The 
> > difficulty I'm having is probably related to the ctypes translation 
> > mechanism from python.  Here's what I'm using in python.  The ctypes module 
> > enables the translation from the C libraries to python and imports the 
> > net-snmp space as libnsa:
> >
> > import ctypes
> > from netsnmpapi import *
> > import netsnmpvartypes
> > libnsa = ctypes.cdll.LoadLibrary(ctypes.util.find_library("netsnmpagent"))
> > ...
> > {code that registers oids from new mib}
> > ...
> > {start subagent}
> > print(libnsa.unregister_mib(b("SNMPv2-MIB::sysContact"), 
> > len("SNMPv2-MIB::sysContact"))
> >
> > This always returns -1, whether I unregister before starting the agent or 
> > after.  I've also tried unregistering some objects from my mib that were 
> > previously registered with the same result.
> 
> This looks like you are calling the unregister_mib c function in a dlopened
> version of netsnmp.
> 
> That function takes a parameter of type array of oid, what exact type oid is
> depends on how your netsnmp library was built but it usually is unsigned long.
> That array should contain the numerical OID value, in your case that would be
> { 1, 3, 6, 1, 2, 1, 1, 4 } but honestly I think an agentx library would serve
> you better.
> 
> /MF
> 
> 
> 
> >      Winston
> > ________________________________
> > From: Larry Hayes <lhay...@gmail.com>
> > Sent: Friday, January 28, 2022 4:48 PM
> > To: Winston Gadsby <wgad...@enginuitycom.com>
> > Cc: net-snmp-coders@lists.sourceforge.net 
> > <net-snmp-coders@lists.sourceforge.net>
> > Subject: Re: Re-registering sysContact and sysLocation with subagent
> >
> > Someone just this month asked about taking control of the system 
> > description.  I would suspect that sysContact and sysLocation would follow 
> > the same way.
> >
> > Their solution was to unregister the OID then register your own handler.
> >
> >
> > unregister_mib() API.
> >
> > https://sourceforge.net/p/net-snmp/mailman/message/37598495/
> >
> >
> > It is a hassle, but you can also control the values of those inside of a 
> > snmpd.local.conf file.
> >
> > syscontact Nobody <nob...@dev.null>
> >
> > Your  agent would write the values to that file then SIGHUP the snmpd to 
> > pick up the changes.
> >
> >
> > On Fri, Jan 28, 2022 at 3:37 PM Winston Gadsby 
> > <wgad...@enginuitycom.com<mailto:wgad...@enginuitycom.com>> wrote:
> > Hi,
> > I'm running a subagent based on python-netsnmpagent, along with the 
> > distribution snmpd (net-snmp) agent on a Debian embedded system.  I'm using 
> > the version of snmpd that comes default with the distribution - 5.7.3.  I 
> > have a custom MIB for my new variables, similar to SIMPLE-MIB.txt in the 
> > python-netsnmpagent example.  Through the standard snmp command line 
> > commands I am able to read and write to the standard MIB defined OIDs, and 
> > to the new OIDs in my MIB, without issue.
> >
> > I would like to also be able to take over management of sysContact and 
> > sysLocation through my subagent.  This makes it easier to control these 
> > variables through my outside gui.  I've tried registering 
> > SNMPv2-MIB::sysContact and SNMPv2-MIB::sysLocation through the agentx 
> > socket, but receive error 263 - duplicate registration.  It seems the 
> > primary agent has already registered these variables and won't give up 
> > control.
> >
> > How does the agent know which variables the subagent can register and which 
> > it cannot?  Is my error due to another cause?  My custom MIB is located in 
> > the same directory as the rest of the system MIBs, in the search path - 
> > /usr/share/snmp/mibs.  When I register a variable from my MIB, the master 
> > agent accepts it.  When I attempt to register sysContact or sysLocation it 
> > is denied.  If all the MIBs are stored together, how does it know my 
> > SIMPLE-MIB objects can be registered, but the others cannot?  Is there 
> > configuration somewhere else that determines which MIB variables I can 
> > register and which I cannot?  Am I only able to register variables in the 
> > new MIB?  How does it know which MIBs are custom and which are standard?  
> > I've checked the snmpd.conf file, and it looks like I can define OID trees 
> > that trigger external programs, but there doesn't appear to be 
> > configuration for which OIDs are under master control and which can be 
> > controlled by the subagent, for normal snmp command line access.
> >
> > Is there perhaps a better way of going about doing this?
> >
> > I've gone through the mail lists and haven't been able to find an answer to 
> > this question.  Any help/pointers on this would be much appreciated.  Thank 
> > you,
> >
> > Winston
> >
> > _______________________________________________
> > Net-snmp-coders mailing list
> > Net-snmp-coders@lists.sourceforge.net<mailto:Net-snmp-coders@lists.sourceforge.net>
> > https://lists.sourceforge.net/lists/listinfo/net-snmp-coders
> 
> 
> > _______________________________________________
> > Net-snmp-coders mailing list
> > Net-snmp-coders@lists.sourceforge.net
> > https://lists.sourceforge.net/lists/listinfo/net-snmp-coders
> 
/* generated from net-snmp-config */
#include <net-snmp/net-snmp-config.h>
#ifdef HAVE_SIGNAL
#include <signal.h>
#endif /* HAVE_SIGNAL */
#ifdef HAVE_SYS_STAT_H
#include <sys/stat.h>
#endif /*  HAVE_SYS_STAT_H */
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif /* HAVE_FCNTL_H */
#include <unistd.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
  #include "sysContact.h"
const char *app_name = "sysContact";
static int reconfig = 0;

extern int netsnmp_running;

RETSIGTYPE
stop_server(int a) {
    netsnmp_running = 0;
}

#ifdef SIGHUP
RETSIGTYPE
hup_handler(int sig)
{
    reconfig = 1;
    signal(SIGHUP, hup_handler);
}
#endif

static void
usage(const char *prog)
{
    fprintf(stderr,
            "USAGE: %s [OPTIONS]\n"
            "\n"
            "OPTIONS:\n", prog);

    fprintf(stderr,
            "  -c FILE[,...]\t\tread FILE(s) as configuration file(s)\n"
            "  -C\t\t\tdo not read the default configuration files\n"
            "  -d\t\t\tdump all traffic\n"
            "  -D TOKEN[,...]\tturn on debugging output for the specified "
            "TOKENs\n"
            "\t\t\t   (ALL gives extremely verbose debugging output)\n"
            "  -f\t\t\tDo not fork() from the calling shell.\n"
            "  -h\t\t\tdisplay this help message\n"
            "  -H\t\t\tdisplay a list of configuration file directives\n"
            "  -L LOGOPTS\t\tToggle various defaults controlling logging:\n");
    snmp_log_options_usage("\t\t\t  ", stderr);
#ifndef DISABLE_MIB_LOADING
    fprintf(stderr,
            "  -m MIB[" ENV_SEPARATOR "...]\t\tload given list of MIBs (ALL loads "
            "everything)\n"
            "  -M DIR[" ENV_SEPARATOR "...]\t\tlook in given list of directories for MIBs\n");
#endif /* DISABLE_MIB_LOADING */
    fprintf(stderr,
            "  -p FILE\t\tstore process id in FILE\n");
#ifndef DISABLE_MIB_LOADING
    fprintf(stderr,
            "  -P MIBOPTS\t\tToggle various defaults controlling mib "
            "parsing:\n");
    snmp_mib_toggle_options_usage("\t\t\t  ", stderr);
#endif /* DISABLE_MIB_LOADING */
    fprintf(stderr,
            "  -v\t\t\tdisplay package version number\n"
            "  -x TRANSPORT\tconnect to master agent using TRANSPORT\n");
    exit(1);
}

static void
version(void)
{
    fprintf(stderr, "NET-SNMP version: %s\n", netsnmp_get_version());
    exit(0);
}

int
main (int argc, char **argv)
{
  int arg;
  char* cp = NULL;
  int dont_fork = 0, do_help = 0;
  char* pid_file = NULL;

  while ((arg = getopt(argc, argv, "c:CdD:fhHL:"
#ifndef DISABLE_MIB_LOADING
                       "m:M:"
#endif /* DISABLE_MIB_LOADING */
                       "n:p:"
#ifndef DISABLE_MIB_LOADING
                       "P:"
#endif /* DISABLE_MIB_LOADING */
                       "vx:")) != EOF) {
    switch (arg) {
      case 'c':
        if (optarg != NULL) {
          netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
                                NETSNMP_DS_LIB_OPTIONALCONFIG, optarg);
        } else {
          usage(argv[0]);
        }
        break;

      case 'C':
        netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
                               NETSNMP_DS_LIB_DONT_READ_CONFIGS, 1);
        break;

    case 'd':
      netsnmp_ds_set_boolean(NETSNMP_DS_LIBRARY_ID,
                             NETSNMP_DS_LIB_DUMP_PACKET, 1);
      break;

    case 'D':
      debug_register_tokens(optarg);
      snmp_set_do_debugging(1);
      break;

    case 'f':
      dont_fork = 1;
      break;

    case 'h':
      usage(argv[0]);
      break;

    case 'H':
      do_help = 1;
      break;

    case 'L':
      if (snmp_log_options(optarg, argc, argv) < 0) {
        exit(1);
      }
      break;

#ifndef DISABLE_MIB_LOADING
    case 'm':
      if (optarg != NULL) {
        setenv("MIBS", optarg, 1);
      } else {
        usage(argv[0]);
      }
      break;

    case 'M':
      if (optarg != NULL) {
        setenv("MIBDIRS", optarg, 1);
      } else {
        usage(argv[0]);
      }
      break;
#endif /* DISABLE_MIB_LOADING */

    case 'n':
      if (optarg != NULL) {
        app_name = optarg;
        netsnmp_ds_set_string(NETSNMP_DS_LIBRARY_ID,
                              NETSNMP_DS_LIB_APPTYPE, app_name);
      } else {
        usage(argv[0]);
      }
      break;

    case 'p':
      if (optarg != NULL) {
        pid_file = optarg;
      } else {
        usage(argv[0]);
      }
      break;

#ifndef DISABLE_MIB_LOADING
    case 'P':
      cp = snmp_mib_toggle_options(optarg);
      if (cp != NULL) {
        fprintf(stderr, "Unknown parser option to -P: %c.\n", *cp);
        usage(argv[0]);
      }
      break;
#endif /* DISABLE_MIB_LOADING */

    case 'v':
      version();
      break;

    case 'x':
      if (optarg != NULL) {
        netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID,
                              NETSNMP_DS_AGENT_X_SOCKET, optarg);
      } else {
        usage(argv[0]);
      }
      break;

    default:
      fprintf(stderr, "invalid option: -%c\n", arg);
      usage(argv[0]);
      break;
    }
  }

  if (do_help) {
    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
                           NETSNMP_DS_AGENT_NO_ROOT_ACCESS, 1);
  } else {
    /* we are a subagent */
    netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID,
                           NETSNMP_DS_AGENT_ROLE, 1);

    if (!dont_fork) {
      if (netsnmp_daemonize(1, snmp_stderrlog_status()) != 0)
        exit(1);
    }

#if HAVE_GETPID
    if (pid_file != NULL) {
      /*
       * unlink the pid_file, if it exists, prior to open.  Without
       * doing this the open will fail if the user specified pid_file
       * already exists.
       */
      int fd;
      unlink(pid_file);
      fd = open(pid_file, O_CREAT | O_EXCL | O_WRONLY, 0600);
      if (fd == -1) {
        snmp_log_perror(pid_file);
        if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID,
                                    NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
          exit(1);
        }
      } else {
        char buf[3 + sizeof(long) * 3];
        int len = snprintf(buf, sizeof(buf), "%ld\n", (long int)getpid());
        write(fd, buf, len);
        close(fd);
      }
    }
#endif

    /* initialize tcpip, if necessary */
    SOCK_STARTUP;
  }

  /* initialize the agent library */
  init_agent(app_name);

  /* initialize your mib code here */
  init_sysContact();

  /* sysContact will be used to read sysContact.conf files. */
  init_snmp("sysContact");

  if (do_help) {
    fprintf(stderr, "Configuration directives understood:\n");
    read_config_print_usage("  ");
    exit(0);
  }

  /* In case we received a request to stop (kill -TERM or kill -INT) */
  netsnmp_running = 1;
#ifdef SIGTERM
  signal(SIGTERM, stop_server);
#endif
#ifdef SIGINT
  signal(SIGINT, stop_server);
#endif
#ifdef SIGHUP
  signal(SIGHUP, hup_handler);
#endif

  /* main loop here... */
  while(netsnmp_running) {
    if (reconfig) {
      free_config();
      read_configs();
      reconfig = 0;
    }
    agent_check_and_process(1);
  }

  /* at shutdown time */
  snmp_shutdown(app_name);

  /* deinitialize your mib code here */

  /* shutdown the agent library */
  shutdown_agent();

  if (pid_file != NULL) {
    unlink(pid_file);
  }

  SOCK_CLEANUP;
  exit(0);
}
/*
 * Note: this file originally auto-generated by mib2c
 * using mib2c.scalar.conf
 */

#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "sysContact.h"

struct pstring { unsigned char len; char data[128]; };
struct pstring sysContact = { 5, "nisse" };

/** Initializes the sysContact module */
void
init_sysContact(void)
{
    const oid       sysContact_oid[] = { 1, 3, 6, 1, 2, 1, 1, 4 };

    DEBUGMSGTL(("sysContact", "Initializing\n"));

    netsnmp_handler_registration* reg =
	netsnmp_create_handler_registration
            ("sysContact", handle_sysContact,
             sysContact_oid, OID_LENGTH(sysContact_oid),
             HANDLER_CAN_RONLY);
    reg->priority = 64;
    netsnmp_register_scalar(reg);
}

int
handle_sysContact(netsnmp_mib_handler *handler,
                  netsnmp_handler_registration *reginfo,
                  netsnmp_agent_request_info *reqinfo,
                  netsnmp_request_info *requests)
{
    /*
     * We are never called for a GETNEXT if it's registered as a
     * "instance", as it's "magically" handled for us.  
     */

    /*
     * a instance handler also only hands us one request at a time, so
     * we don't need to loop over a list of requests; we'll only get one. 
     */

    switch (reqinfo->mode) {

    case MODE_GET:
        snmp_set_var_typed_value(requests->requestvb, ASN_OCTET_STR,
				 sysContact.data, sysContact.len);
        break;

    default:
        /*
         * we should never get here, so this is a really bad error 
         */
        snmp_log(LOG_ERR, "unknown mode (%d) in handle_sysContact\n",
                 reqinfo->mode);
        return SNMP_ERR_GENERR;
    }

    return SNMP_ERR_NOERROR;
}
/*
 * Note: this file originally auto-generated by mib2c
 * using mib2c.scalar.conf
 */
#ifndef SYSCONTACT_H
#define SYSCONTACT_H

/*
 * function declarations 
 */
void            init_sysContact(void);
Netsnmp_Node_Handler handle_sysContact;

#endif                          /* SYSCONTACT_H */
_______________________________________________
Net-snmp-coders mailing list
Net-snmp-coders@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/net-snmp-coders

Reply via email to