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