4 #include <net-snmp/net-snmp-config.h>
10 #if TIME_WITH_SYS_TIME
12 # include <sys/timeb.h>
14 # include <sys/time.h>
19 # include <sys/time.h>
28 #include <sys/socket.h>
36 #include <netinet/in.h>
43 #include <net-snmp/net-snmp-includes.h>
44 #include <net-snmp/agent/net-snmp-agent-includes.h>
45 #include <net-snmp/library/snmp_assert.h>
48 #include "agentx/protocol.h"
49 #include "agentx/client.h"
50 #include <net-snmp/agent/agent_callbacks.h>
51 #include <net-snmp/agent/agent_trap.h>
52 #ifdef USING_MIBII_SYSORTABLE_MODULE
53 #include "mibII/sysORTable.h"
58 static SNMPCallback subagent_register_ping_alarm;
59 static SNMPAlarmCallback agentx_reopen_session;
60 void agentx_register_callbacks(netsnmp_session * s);
61 void agentx_unregister_callbacks(netsnmp_session * ss);
62 int handle_subagent_response(int op, netsnmp_session * session,
63 int reqid, netsnmp_pdu *pdu,
65 int handle_subagent_set_response(int op,
66 netsnmp_session * session,
67 int reqid, netsnmp_pdu *pdu,
70 typedef struct _net_snmpsubagent_magic_s {
72 netsnmp_session *session;
73 netsnmp_variable_list *ovars;
76 struct agent_netsnmp_set_info {
81 netsnmp_session *sess;
82 netsnmp_variable_list *var_list;
84 struct agent_netsnmp_set_info *next;
87 static struct agent_netsnmp_set_info *Sets = NULL;
89 netsnmp_session *agentx_callback_sess = NULL;
90 extern int callback_master_num;
95 if (agentx_callback_sess == NULL) {
96 agentx_callback_sess = netsnmp_callback_open(callback_master_num,
97 handle_subagent_response,
99 DEBUGMSGTL(("agentx/subagent", "init_subagent sess %08x\n",
100 agentx_callback_sess));
105 struct agent_netsnmp_set_info *
106 save_set_vars(netsnmp_session * ss, netsnmp_pdu *pdu)
108 struct agent_netsnmp_set_info *ptr;
110 extern struct timeval starttime;
112 ptr = (struct agent_netsnmp_set_info *)
113 malloc(sizeof(struct agent_netsnmp_set_info));
118 * Save the important information
120 ptr->transID = pdu->transid;
122 ptr->mode = SNMP_MSG_INTERNAL_SET_RESERVE1;
123 gettimeofday(&now, NULL);
124 ptr->uptime = calculate_time_diff(&now, &starttime);
126 ptr->var_list = snmp_clone_varbind(pdu->variables);
127 if (ptr->var_list == NULL) {
138 struct agent_netsnmp_set_info *
139 restore_set_vars(netsnmp_session * sess, netsnmp_pdu *pdu)
141 struct agent_netsnmp_set_info *ptr;
143 for (ptr = Sets; ptr != NULL; ptr = ptr->next)
144 if (ptr->sess == sess && ptr->transID == pdu->transid)
147 if (ptr == NULL || ptr->var_list == NULL)
150 pdu->variables = snmp_clone_varbind(ptr->var_list);
151 if (pdu->variables == NULL)
159 free_set_vars(netsnmp_session * ss, netsnmp_pdu *pdu)
161 struct agent_netsnmp_set_info *ptr, *prev = NULL;
163 for (ptr = Sets; ptr != NULL; ptr = ptr->next) {
164 if (ptr->sess == ss && ptr->transID == pdu->transid) {
166 prev->next = ptr->next;
169 snmp_free_varbind(ptr->var_list);
177 extern netsnmp_session *main_session; /* from snmp_agent.c */
180 handle_agentx_packet(int operation, netsnmp_session * session, int reqid,
181 netsnmp_pdu *pdu, void *magic)
183 struct agent_netsnmp_set_info *asi = NULL;
184 snmp_callback mycallback;
185 netsnmp_pdu *internal_pdu = NULL;
186 void *retmagic = NULL;
187 ns_subagent_magic *smagic = NULL;
189 if (operation == NETSNMP_CALLBACK_OP_DISCONNECT) {
191 netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL);
192 DEBUGMSGTL(("agentx/subagent",
193 "transport disconnect indication\n"));
195 * Deregister the ping alarm, if any, and invalidate all other
196 * references to this session.
198 if (session->securityModel != SNMP_DEFAULT_SECMODEL) {
199 snmp_alarm_unregister(session->securityModel);
201 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
202 SNMPD_CALLBACK_INDEX_STOP, (void *) session);
203 agentx_unregister_callbacks(session);
204 remove_trap_session(session);
205 register_mib_detach();
209 * Pings are enabled, so periodically attempt to re-establish contact
210 * with the master agent. Don't worry about the handle,
211 * agentx_reopen_session unregisters itself if it succeeds in talking
212 * to the master agent.
214 snmp_alarm_register(period, SA_REPEAT, agentx_reopen_session,
218 } else if (operation != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
219 DEBUGMSGTL(("agentx/subagent", "unexpected callback op %d\n",
225 * ok, we have a pdu from the net. Modify as needed
228 DEBUGMSGTL(("agentx/subagent", "handling agentx request (req=0x%x,trans="
229 "0x%x,sess=0x%x)\n", pdu->reqid,pdu->transid, pdu->sessid));
230 pdu->version = AGENTX_VERSION_1;
231 pdu->flags |= UCD_MSG_FLAG_ALWAYS_IN_VIEW;
233 if (pdu->command == AGENTX_MSG_GET
234 || pdu->command == AGENTX_MSG_GETNEXT
235 || pdu->command == AGENTX_MSG_GETBULK) {
237 (ns_subagent_magic *) calloc(1, sizeof(ns_subagent_magic));
238 if (smagic == NULL) {
239 DEBUGMSGTL(("agentx/subagent", "couldn't malloc() smagic\n"));
242 smagic->original_command = pdu->command;
243 smagic->session = session;
244 smagic->ovars = NULL;
245 retmagic = (void *) smagic;
248 switch (pdu->command) {
250 DEBUGMSGTL(("agentx/subagent", " -> get\n"));
251 pdu->command = SNMP_MSG_GET;
252 mycallback = handle_subagent_response;
255 case AGENTX_MSG_GETNEXT:
256 DEBUGMSGTL(("agentx/subagent", " -> getnext\n"));
257 pdu->command = SNMP_MSG_GETNEXT;
260 * We have to save a copy of the original variable list here because
261 * if the master agent has requested scoping for some of the varbinds
262 * that information is stored there.
265 smagic->ovars = snmp_clone_varbind(pdu->variables);
266 DEBUGMSGTL(("agentx/subagent", "saved variables\n"));
267 mycallback = handle_subagent_response;
270 case AGENTX_MSG_GETBULK:
274 DEBUGMSGTL(("agentx/subagent", " -> getbulk\n"));
275 pdu->command = SNMP_MSG_GETBULK;
278 * We have to save a copy of the original variable list here because
279 * if the master agent has requested scoping for some of the varbinds
280 * that information is stored there.
283 smagic->ovars = snmp_clone_varbind(pdu->variables);
284 DEBUGMSGTL(("agentx/subagent", "saved variables at %p\n",
286 mycallback = handle_subagent_response;
289 case AGENTX_MSG_RESPONSE:
290 DEBUGMSGTL(("agentx/subagent", " -> response\n"));
293 case AGENTX_MSG_TESTSET:
295 * XXXWWW we have to map this twice to both RESERVE1 and RESERVE2
297 DEBUGMSGTL(("agentx/subagent", " -> testset\n"));
298 asi = save_set_vars(session, pdu);
300 snmp_log(LOG_WARNING, "save_set_vars() failed\n");
303 asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_RESERVE1;
304 mycallback = handle_subagent_set_response;
308 case AGENTX_MSG_COMMITSET:
309 DEBUGMSGTL(("agentx/subagent", " -> commitset\n"));
310 asi = restore_set_vars(session, pdu);
312 snmp_log(LOG_WARNING, "restore_set_vars() failed\n");
315 if (asi->mode != SNMP_MSG_INTERNAL_SET_RESERVE2) {
316 snmp_log(LOG_WARNING,
317 "dropping bad AgentX request (wrong mode %d)\n",
321 asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_ACTION;
322 mycallback = handle_subagent_set_response;
326 case AGENTX_MSG_CLEANUPSET:
327 DEBUGMSGTL(("agentx/subagent", " -> cleanupset\n"));
328 asi = restore_set_vars(session, pdu);
330 snmp_log(LOG_WARNING, "restore_set_vars() failed\n");
333 if (asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE1 ||
334 asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE2) {
335 asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_FREE;
336 } else if (asi->mode == SNMP_MSG_INTERNAL_SET_ACTION) {
337 asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_COMMIT;
339 snmp_log(LOG_WARNING,
340 "dropping bad AgentX request (wrong mode %d)\n",
344 mycallback = handle_subagent_set_response;
348 case AGENTX_MSG_UNDOSET:
349 DEBUGMSGTL(("agentx/subagent", " -> undoset\n"));
350 asi = restore_set_vars(session, pdu);
352 snmp_log(LOG_WARNING, "restore_set_vars() failed\n");
355 asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_UNDO;
356 mycallback = handle_subagent_set_response;
361 DEBUGMSGTL(("agentx/subagent", " -> unknown command %d (%02x)\n",
362 pdu->command, pdu->command));
367 * submit the pdu to the internal handler
371 * We have to clone the PDU here, because when we return from this
372 * callback, sess_process_packet will free(pdu), but this call also
373 * free()s its argument PDU.
376 internal_pdu = snmp_clone_pdu(pdu);
377 snmp_async_send(agentx_callback_sess, internal_pdu, mycallback,
383 handle_subagent_response(int op, netsnmp_session * session, int reqid,
384 netsnmp_pdu *pdu, void *magic)
386 ns_subagent_magic *smagic = (ns_subagent_magic *) magic;
387 netsnmp_variable_list *u = NULL, *v = NULL;
390 if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE || magic == NULL) {
394 pdu = snmp_clone_pdu(pdu);
395 DEBUGMSGTL(("agentx/subagent",
396 "handling AgentX response (cmd 0x%02x orig_cmd 0x%02x)\n",
397 pdu->command, smagic->original_command));
399 if (pdu->command == SNMP_MSG_INTERNAL_SET_FREE ||
400 pdu->command == SNMP_MSG_INTERNAL_SET_UNDO ||
401 pdu->command == SNMP_MSG_INTERNAL_SET_COMMIT) {
402 free_set_vars(smagic->session, pdu);
405 if (smagic->original_command == AGENTX_MSG_GETNEXT) {
406 DEBUGMSGTL(("agentx/subgaent",
407 "do getNext scope processing %p %p\n", smagic->ovars,
409 for (u = smagic->ovars, v = pdu->variables; u != NULL && v != NULL;
410 u = u->next_variable, v = v->next_variable) {
412 (u->val.objid, u->val_len / sizeof(oid), nullOid,
415 * The master agent requested scoping for this variable.
417 rc = snmp_oid_compare(v->name, v->name_length,
419 u->val_len / sizeof(oid));
420 DEBUGMSGTL(("agentx/subagent", "result "));
421 DEBUGMSGOID(("agentx/subagent", v->name, v->name_length));
422 DEBUGMSG(("agentx/subagent", " scope to "));
423 DEBUGMSGOID(("agentx/subagent",
424 u->val.objid, u->val_len / sizeof(oid)));
425 DEBUGMSG(("agentx/subagent", " result %d\n", rc));
429 * The varbind is out of scope. From RFC2741, p. 66: "If
430 * the subagent cannot locate an appropriate variable,
431 * v.name is set to the starting OID, and the VarBind is
432 * set to `endOfMibView'".
434 snmp_set_var_objid(v, u->name, u->name_length);
435 snmp_set_var_typed_value(v, SNMP_ENDOFMIBVIEW, 0, 0);
436 DEBUGMSGTL(("agentx/subagent",
437 "scope violation -- return endOfMibView\n"));
440 DEBUGMSGTL(("agentx/subagent", "unscoped var\n"));
446 * XXXJBPN: similar for GETBULK but the varbinds can get re-ordered I
447 * think which makes it er more difficult.
450 if (smagic->ovars != NULL) {
451 snmp_free_varbind(smagic->ovars);
454 pdu->command = AGENTX_MSG_RESPONSE;
455 pdu->version = smagic->session->version;
457 if (!snmp_send(smagic->session, pdu)) {
460 DEBUGMSGTL(("agentx/subagent", " FINISHED\n"));
466 handle_subagent_set_response(int op, netsnmp_session * session, int reqid,
467 netsnmp_pdu *pdu, void *magic)
469 netsnmp_session *retsess;
470 struct agent_netsnmp_set_info *asi;
472 if (op != NETSNMP_CALLBACK_OP_RECEIVED_MESSAGE || magic == NULL) {
476 DEBUGMSGTL(("agentx/subagent",
477 "handling agentx subagent set response (mode=%d,req=0x%x,"
478 "trans=0x%x,sess=0x%x)\n",
479 pdu->command, pdu->reqid,pdu->transid, pdu->sessid));
480 pdu = snmp_clone_pdu(pdu);
482 asi = (struct agent_netsnmp_set_info *) magic;
484 asi->errstat = pdu->errstat;
486 if (asi->mode == SNMP_MSG_INTERNAL_SET_RESERVE1) {
488 * reloop for RESERVE2 mode, an internal only agent mode
491 * XXX: check exception statuses of reserve1 first
494 asi->mode = pdu->command = SNMP_MSG_INTERNAL_SET_RESERVE2;
495 snmp_async_send(agentx_callback_sess, pdu,
496 handle_subagent_set_response, asi);
497 DEBUGMSGTL(("agentx/subagent",
498 " going from RESERVE1 -> RESERVE2\n"));
502 if (asi->mode == SNMP_MSG_INTERNAL_SET_FREE ||
503 asi->mode == SNMP_MSG_INTERNAL_SET_UNDO ||
504 asi->mode == SNMP_MSG_INTERNAL_SET_COMMIT) {
505 free_set_vars(retsess, pdu);
507 pdu->variables = NULL; /* the variables were added by us */
510 netsnmp_assert(retsess != NULL);
511 pdu->command = AGENTX_MSG_RESPONSE;
512 pdu->version = retsess->version;
514 if (!snmp_send(retsess, pdu)) {
517 DEBUGMSGTL(("agentx/subagent", " FINISHED\n"));
524 agentx_registration_callback(int majorID, int minorID, void *serverarg,
527 struct register_parameters *reg_parms =
528 (struct register_parameters *) serverarg;
529 netsnmp_session *agentx_ss = (netsnmp_session *) clientarg;
531 if (minorID == SNMPD_CALLBACK_REGISTER_OID)
532 return agentx_register(agentx_ss,
533 reg_parms->name, reg_parms->namelen,
535 reg_parms->range_subid,
536 reg_parms->range_ubound, reg_parms->timeout,
539 return agentx_unregister(agentx_ss,
540 reg_parms->name, reg_parms->namelen,
542 reg_parms->range_subid,
543 reg_parms->range_ubound);
547 #ifdef USING_MIBII_SYSORTABLE_MODULE
549 agentx_sysOR_callback(int majorID, int minorID, void *serverarg,
552 struct register_sysOR_parameters *reg_parms =
553 (struct register_sysOR_parameters *) serverarg;
554 netsnmp_session *agentx_ss = (netsnmp_session *) clientarg;
556 if (minorID == SNMPD_CALLBACK_REG_SYSOR)
557 return agentx_add_agentcaps(agentx_ss,
558 reg_parms->name, reg_parms->namelen,
561 return agentx_remove_agentcaps(agentx_ss,
569 subagent_shutdown(int majorID, int minorID, void *serverarg, void *clientarg)
571 netsnmp_session *thesession = (netsnmp_session *)clientarg;
572 DEBUGMSGTL(("agentx/subagent", "shutting down session....\n"));
573 if (thesession == NULL) {
574 DEBUGMSGTL(("agentx/subagent", "Empty session to shutdown\n"));
578 agentx_close_session(thesession, AGENTX_CLOSE_SHUTDOWN);
579 snmp_close(thesession);
581 DEBUGMSGTL(("agentx/subagent", "shut down finished.\n"));
588 * Register all the "standard" AgentX callbacks for the given session.
592 agentx_register_callbacks(netsnmp_session * s)
594 DEBUGMSGTL(("agentx/subagent",
595 "registering callbacks for session %p\n", s));
596 snmp_register_callback(SNMP_CALLBACK_LIBRARY,
597 SNMP_CALLBACK_POST_READ_CONFIG,
598 subagent_register_ping_alarm, s);
599 snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN,
600 subagent_shutdown, s);
601 snmp_register_callback(SNMP_CALLBACK_APPLICATION,
602 SNMPD_CALLBACK_REGISTER_OID,
603 agentx_registration_callback, s);
604 snmp_register_callback(SNMP_CALLBACK_APPLICATION,
605 SNMPD_CALLBACK_UNREGISTER_OID,
606 agentx_registration_callback, s);
607 #ifdef USING_MIBII_SYSORTABLE_MODULE
608 snmp_register_callback(SNMP_CALLBACK_APPLICATION,
609 SNMPD_CALLBACK_REG_SYSOR,
610 agentx_sysOR_callback, s);
611 snmp_register_callback(SNMP_CALLBACK_APPLICATION,
612 SNMPD_CALLBACK_UNREG_SYSOR,
613 agentx_sysOR_callback, s);
618 * Unregister all the callbacks associated with this session.
622 agentx_unregister_callbacks(netsnmp_session * ss)
624 DEBUGMSGTL(("agentx/subagent",
625 "unregistering callbacks for session %p\n", ss));
626 snmp_unregister_callback(SNMP_CALLBACK_LIBRARY,
627 SNMP_CALLBACK_POST_READ_CONFIG,
628 subagent_register_ping_alarm, ss, 1);
629 snmp_unregister_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_SHUTDOWN,
630 subagent_shutdown, ss, 1);
631 snmp_unregister_callback(SNMP_CALLBACK_APPLICATION,
632 SNMPD_CALLBACK_REGISTER_OID,
633 agentx_registration_callback, ss, 1);
634 snmp_unregister_callback(SNMP_CALLBACK_APPLICATION,
635 SNMPD_CALLBACK_UNREGISTER_OID,
636 agentx_registration_callback, ss, 1);
637 #ifdef USING_MIBII_SYSORTABLE_MODULE
638 snmp_unregister_callback(SNMP_CALLBACK_APPLICATION,
639 SNMPD_CALLBACK_REG_SYSOR,
640 agentx_sysOR_callback, ss, 1);
641 snmp_unregister_callback(SNMP_CALLBACK_APPLICATION,
642 SNMPD_CALLBACK_UNREG_SYSOR,
643 agentx_sysOR_callback, ss, 1);
649 * Open a session to the master agent.
652 subagent_open_master_session(void)
654 netsnmp_session sess;
656 DEBUGMSGTL(("agentx/subagent", "opening session...\n"));
659 snmp_log(LOG_WARNING,
660 "AgentX session to master agent attempted to be re-opened.");
664 snmp_sess_init(&sess);
665 sess.version = AGENTX_VERSION_1;
666 sess.retries = SNMP_DEFAULT_RETRIES;
667 sess.timeout = SNMP_DEFAULT_TIMEOUT;
668 sess.flags |= SNMP_FLAGS_STREAM_SOCKET;
669 if (netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET)) {
671 netsnmp_ds_get_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_X_SOCKET);
673 sess.peername = strdup(AGENTX_SOCKET);
676 sess.local_port = 0; /* client */
677 sess.remote_port = AGENTX_PORT; /* default port */
678 sess.callback = handle_agentx_packet;
679 sess.authenticator = NULL;
680 main_session = snmp_open_ex(&sess, NULL, agentx_parse, NULL, NULL,
681 agentx_realloc_build, agentx_check_packet);
683 if (main_session == NULL) {
685 * Diagnose snmp_open errors with the input
686 * netsnmp_session pointer.
688 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_CONNECTION_WARNINGS)) {
689 if (!netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_NO_ROOT_ACCESS)) {
690 netsnmp_sess_log_error(LOG_WARNING,
691 "Error: Failed to connect to the agentx master agent",
695 ("Error: Failed to connect to the agentx master agent",
702 if (agentx_open_session(main_session) < 0) {
703 snmp_close(main_session);
708 if (add_trap_session(main_session, AGENTX_MSG_NOTIFY, 1,
710 DEBUGMSGTL(("agentx/subagent", " trap session registered OK\n"));
712 DEBUGMSGTL(("agentx/subagent",
713 "trap session registration failed\n"));
714 snmp_close(main_session);
719 agentx_register_callbacks(main_session);
721 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
722 SNMPD_CALLBACK_INDEX_START, (void *) main_session);
724 DEBUGMSGTL(("agentx/subagent", "opening session... DONE (%p)\n",
731 * returns non-zero on error
734 subagent_pre_init(void)
736 DEBUGMSGTL(("agentx/subagent", "initializing....\n"));
739 * set up callbacks to initiate master agent pings for this session
741 netsnmp_ds_register_config(ASN_INTEGER,
742 netsnmp_ds_get_string(NETSNMP_DS_LIBRARY_ID, NETSNMP_DS_LIB_APPTYPE),
743 "agentxPingInterval",
744 NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL);
747 if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) != SUB_AGENT) {
752 * if a valid ping interval has been defined, call agentx_reopen_session
753 * * to try to connect to master or setup a ping alarm if it couldn't
756 if (netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL) > 0)
757 agentx_reopen_session(0, NULL);
758 else /* if no ping interval was set up, just try to connect once */
759 subagent_open_master_session();
763 DEBUGMSGTL(("agentx/subagent", "initializing.... DONE\n"));
770 * Alarm callback function to open a session to the master agent. If a
771 * transport disconnection callback occurs, indicating that the master agent
772 * has died (or there has been some strange communication problem), this
773 * alarm is called repeatedly to try to re-open the connection.
777 agentx_reopen_session(unsigned int clientreg, void *clientarg)
779 DEBUGMSGTL(("agentx/subagent", "agentx_reopen_session(%d) called\n",
782 if (subagent_open_master_session() == 0) {
784 * Successful. Delete the alarm handle if one exists.
786 if (clientreg != 0) {
787 snmp_alarm_unregister(clientreg);
791 * Reregister all our nodes.
793 register_mib_reattach();
796 * Register a ping alarm (if need be).
798 subagent_register_ping_alarm(0, 0, 0, main_session);
800 if (clientreg == 0) {
802 * Register a reattach alarm for later
804 subagent_register_ping_alarm(0, 0, 0, main_session);
810 * If a valid session is passed in (through clientarg), register a
811 * ping handler to ping it frequently, else register an attempt to try
812 * and open it again later.
816 subagent_register_ping_alarm(int majorID, int minorID,
817 void *serverarg, void *clientarg)
820 netsnmp_session *ss = (netsnmp_session *) clientarg;
822 netsnmp_ds_get_int(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_AGENTX_PING_INTERVAL);
824 if (!ping_interval) /* don't do anything if not setup properly */
828 * register a ping alarm, if desired
831 if (ss->securityModel != SNMP_DEFAULT_SECMODEL) {
832 DEBUGMSGTL(("agentx/subagent",
833 "unregister existing alarm %d\n",
835 snmp_alarm_unregister(ss->securityModel);
838 DEBUGMSGTL(("agentx/subagent",
839 "register ping alarm every %d seconds\n",
842 * we re-use the securityModel parameter for an alarm stash,
843 * since agentx doesn't need it
845 ss->securityModel = snmp_alarm_register(ping_interval, SA_REPEAT,
846 agentx_check_session, ss);
849 * attempt to open it later instead
851 DEBUGMSGTL(("agentx/subagent",
852 "subagent not properly attached, postponing registration till later....\n"));
853 snmp_alarm_register(ping_interval, SA_REPEAT,
854 agentx_reopen_session, NULL);
860 * check a session validity for connectivity to the master agent. If
861 * not functioning, close and start attempts to reopen the session
864 agentx_check_session(unsigned int clientreg, void *clientarg)
866 netsnmp_session *ss = (netsnmp_session *) clientarg;
869 snmp_alarm_unregister(clientreg);
872 DEBUGMSGTL(("agentx/subagent", "checking status of session %p\n", ss));
874 if (!agentx_send_ping(ss)) {
875 snmp_log(LOG_WARNING,
876 "AgentX master agent failed to respond to ping. Attempting to re-register.\n");
878 * master agent disappeared? Try and re-register.
879 * close first, just to be sure .
881 agentx_unregister_callbacks(ss);
882 agentx_close_session(ss, AGENTX_CLOSE_TIMEOUT);
883 snmp_alarm_unregister(clientreg); /* delete ping alarm timer */
884 snmp_call_callbacks(SNMP_CALLBACK_APPLICATION,
885 SNMPD_CALLBACK_INDEX_STOP, (void *) ss);
886 snmp_close(main_session);
888 agentx_reopen_session(0, NULL);
890 DEBUGMSGTL(("agentx/subagent", "session %p responded to ping\n",