[Can you please *NOT* send messages to both mailing lists.
     It just adds to the support load unnecessarily.  I usually
     delete such messages without responding.  I'm making an
     exception this time because of the subject matter.]


On Thu, 2006-02-02 at 21:31 +0200, Makavy, Erez (Erez) wrote:
> Questions 1
> ------------------
> Is there a multi-thread problem with using send_v2trap() in the main
> process, while the agent_check_and_process() thread is running?
> (I guess the answer is that there is a problem, because both threads
> require the same socket for sending agentX PDUs.)

There is certainly a problem with heavily loaded master/subagent
communication running into deadlock.  As with many run-time problems,
the underlying causes are subtle and difficult to pin down.



> Proposed solution
> ---------------------------
> - Open a session over Unix Domain socket (so that the
> agent_check_and_process() will listen on it)
> - my main process will write the trap parameters to that socket.
> - In the callback funciton of that session, instead of parsing an
> agentX PDU,
>   I'll read the parameters from the socket, and invoke send_v2Trap().

That sounds vaguely similar to an idea I've been toying with for
some time.   Namely, registering *two* AgentX sessions, using
one for "agent-initiated" communication (traps and pings), and
the other for "master-initiated" communication (SNMP requests).

I'm appending a simple patch intended as a provisional implementation
of such an approach.   It's by far from complete, but I'd be
interested in hearing how well it works for you?

Dave
--- snmp_agent.c.orig	Fri Oct 15 11:08:55 2004
+++ snmp_agent.c	Fri Oct 15 11:24:49 2004
@@ -404,9 +404,9 @@
 {
     int             i, n = 0, r = 0;
     int             repeats = asp->pdu->errindex;
-    int             j;
+    int             j, k;
     int             all_eoMib;
-    netsnmp_variable_list *prev = NULL;
+    netsnmp_variable_list *prev = NULL, *curr;
             
     if (asp->vbcount == 0)  /* Nothing to do! */
         return;
@@ -424,35 +424,48 @@
     if (r == 0)
         return;
             
-    /*
-     * For each of the original repeating varbinds (except the last),
-     *  go through the block of results for that varbind,
-     *  and link each instance to the corresponding instance
-     *  in the next block.
-     */
-    for (i = 0; i < r - 1; i++) {
+    /* Fix endOfMibView entries. */
+    for (i = 0; i < r; i++) {
         prev = NULL;
         for (j = 0; j < repeats; j++) {
+	    curr = asp->bulkcache[i * repeats + j];
             /*
              *  If we don't have a valid name for a given repetition
              *   (and probably for all the ones that follow as well),
-             *   extend the previous result to indicate 'endOfMibView'
+             *   extend the previous result to indicate 'endOfMibView'.
+             *  Or if the repetition already has type endOfMibView make
+             *   sure it has the correct objid (i.e. that of the previous
+             *   entry or that of the original request).
              */
-            if (asp->bulkcache[i * repeats + j]->name_length == 0
-                && prev) {
-                snmp_set_var_objid(
-                    asp->bulkcache[i * repeats + j],
-                    prev->name, prev->name_length);
-                snmp_set_var_typed_value(
-                    asp->bulkcache[i * repeats + j],
-                    SNMP_ENDOFMIBVIEW, NULL, 0);
+            if (curr->name_length == 0 || curr->type == SNMP_ENDOFMIBVIEW) {
+		if (prev == NULL) {
+		    /* Use objid from original pdu. */
+		    prev = asp->orig_pdu->variables;
+		    for (k = i; prev && k > 0; k--)
+			prev = prev->next_variable;
+		}
+		if (prev) {
+		    snmp_set_var_objid(curr, prev->name, prev->name_length);
+		    snmp_set_var_typed_value(curr, SNMP_ENDOFMIBVIEW, NULL, 0);
+		}
             }
-            prev = asp->bulkcache[i * repeats + j];
+            prev = curr;
+        }
+    }
 
+    /*
+     * For each of the original repeating varbinds (except the last),
+     *  go through the block of results for that varbind,
+     *  and link each instance to the corresponding instance
+     *  in the next block.
+     */
+    for (i = 0; i < r - 1; i++) {
+        for (j = 0; j < repeats; j++) {
             asp->bulkcache[i * repeats + j]->next_variable =
                 asp->bulkcache[(i + 1) * repeats + j];
         }
     }
+
     /*
      * For the last of the original repeating varbinds,
      *  go through that block of results, and link each
@@ -461,37 +474,9 @@
      * The very last instance of this block is left untouched
      *  since it (correctly) points to the end of the list.
      */
-    if (r > 0) {
-        prev = NULL;
-        for (j = 0; j < repeats - 1; j++) {
-            /*
-             *  Fill in missing names with 'endOfMibView' as above...
-             */
-            if (asp->bulkcache[(r - 1) * repeats + j]->name_length == 0
-                && prev) {
-                snmp_set_var_objid(
-                    asp->bulkcache[(r - 1) * repeats + j],
-                    prev->name, prev->name_length);
-                snmp_set_var_typed_value(
-                    asp->bulkcache[(r - 1) * repeats + j],
-                    SNMP_ENDOFMIBVIEW, NULL, 0);
-            }
-            prev = asp->bulkcache[(r - 1) * repeats + j];
-            asp->bulkcache[(r - 1) * repeats + j]->next_variable =
-                asp->bulkcache[j + 1];
-        }
-        /*
-         *  ... Not forgetting the very last entry
-         */
-        if (asp->bulkcache[r * repeats - 1]->name_length == 0
-            && prev) {
-            snmp_set_var_objid(
-                asp->bulkcache[r * repeats - 1],
-                prev->name, prev->name_length);
-            snmp_set_var_typed_value(
-                asp->bulkcache[r * repeats - 1],
-                SNMP_ENDOFMIBVIEW, NULL, 0);
-        }
+    for (j = 0; j < repeats - 1; j++) {
+	asp->bulkcache[(r - 1) * repeats + j]->next_variable = 
+	    asp->bulkcache[j + 1];
     }
 
     /*
@@ -532,6 +517,27 @@
 }
 
 
+/* EndOfMibView replies to a GETNEXT request should according to RFC3416
+ *  have the object ID set to that of the request. Our tree search 
+ *  algorithm will sometimes break that requirement. This function will
+ *  fix that.
+ */
+NETSNMP_STATIC_INLINE void
+_fix_endofmibview(netsnmp_agent_session *asp)
+{
+    netsnmp_variable_list *vb, *ovb;
+
+    if (asp->vbcount == 0)  /* Nothing to do! */
+        return;
+
+    for (vb = asp->pdu->variables, ovb = asp->orig_pdu->variables;
+	 vb && ovb; vb = vb->next_variable, ovb = ovb->next_variable) {
+	if (vb->type == SNMP_ENDOFMIBVIEW)
+	    snmp_set_var_objid(vb, ovb->name, ovb->name_length);
+    }
+}
+
+
 int
 getNextSessID()
 {
@@ -1499,6 +1505,10 @@
                  * some stuff needs to be saved in special subagent cases 
                  */
                 save_set_cache(asp);
+                break;
+
+            case SNMP_MSG_GETNEXT:
+                _fix_endofmibview(asp);
                 break;
 
             case SNMP_MSG_GETBULK:

Reply via email to