]> git.proxmox.com Git - mirror_frr.git/blobdiff - lib/smux.c
*: make consistent & update GPLv2 file headers
[mirror_frr.git] / lib / smux.c
index 7e443e3c42e11bcadf2eb98542eb22a7cceeb1f0..032801f6dfabf46c24eb95283c34b33365313ac7 100644 (file)
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with GNU Zebra; see the file COPYING.  If not, write to the Free
- * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.  
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
 
-#ifdef HAVE_SNMP
-#ifdef HAVE_NETSNMP
+#ifdef SNMP_SMUX
 #include <net-snmp/net-snmp-config.h>
-#endif
-#include <asn1.h>
-#include <snmp.h>
-#include <snmp_impl.h>
+#include <net-snmp/net-snmp-includes.h>
 
 #include "log.h"
 #include "thread.h"
 #include "sockunion.h"
 #include "smux.h"
 
+#define SMUX_PORT_DEFAULT 199
+
+#define SMUXMAXPKTSIZE    1500
+#define SMUXMAXSTRLEN      256
+
+#define SMUX_OPEN       (ASN_APPLICATION | ASN_CONSTRUCTOR | 0)
+#define SMUX_CLOSE      (ASN_APPLICATION | ASN_PRIMITIVE | 1)
+#define SMUX_RREQ       (ASN_APPLICATION | ASN_CONSTRUCTOR | 2)
+#define SMUX_RRSP       (ASN_APPLICATION | ASN_PRIMITIVE | 3)
+#define SMUX_SOUT       (ASN_APPLICATION | ASN_PRIMITIVE | 4)
+
+#define SMUX_GET        (ASN_CONTEXT | ASN_CONSTRUCTOR | 0)
+#define SMUX_GETNEXT    (ASN_CONTEXT | ASN_CONSTRUCTOR | 1)
+#define SMUX_GETRSP     (ASN_CONTEXT | ASN_CONSTRUCTOR | 2)
+#define SMUX_SET       (ASN_CONTEXT | ASN_CONSTRUCTOR | 3)
+#define SMUX_TRAP      (ASN_CONTEXT | ASN_CONSTRUCTOR | 4)
+
+#define SMUX_MAX_FAILURE 3
+
+/* SNMP tree. */
+struct subtree
+{
+  /* Tree's oid. */
+  oid name[MAX_OID_LEN];
+  u_char name_len;
+
+  /* List of the variables. */
+  struct variable *variables;
+
+  /* Length of the variables list. */
+  int variables_num;
+
+  /* Width of the variables list. */
+  int variables_width;
+
+  /* Registered flag. */
+  int registered;
+};
+
 #define min(A,B) ((A) < (B) ? (A) : (B))
 
 enum smux_event {SMUX_SCHEDULE, SMUX_CONNECT, SMUX_READ};
 
 void smux_event (enum smux_event, int);
-\f
+
 
 /* SMUX socket. */
 int smux_sock = -1;
@@ -52,16 +86,11 @@ int smux_sock = -1;
 struct list *treelist;
 
 /* SMUX oid. */
-oid *smux_oid;
+oid *smux_oid = NULL;
 size_t smux_oid_len;
 
-/* SMUX default oid. */
-oid *smux_default_oid;
-size_t smux_default_oid_len;
-
 /* SMUX password. */
-char *smux_passwd;
-const char *smux_default_passwd = "";
+char *smux_passwd = NULL;
 
 /* SMUX read threads. */
 struct thread *smux_read_thread;
@@ -76,72 +105,16 @@ int debug_smux = 0;
 int fail = 0;
 
 /* SMUX node. */
-struct cmd_node smux_node =
+static struct cmd_node smux_node =
 {
   SMUX_NODE,
   ""                            /* SMUX has no interface. */
 };
 
 /* thread master */
-static struct thread_master *master;
-\f
-void *
-oid_copy (void *dest, void *src, size_t size)
-{
-  return memcpy (dest, src, size * sizeof (oid));
-}
-
-void
-oid2in_addr (oid oid[], int len, struct in_addr *addr)
-{
-  int i;
-  u_char *pnt;
-  
-  if (len == 0)
-    return;
-
-  pnt = (u_char *) addr;
-
-  for (i = 0; i < len; i++)
-    *pnt++ = oid[i];
-}
-
-void
-oid_copy_addr (oid oid[], struct in_addr *addr, int len)
-{
-  int i;
-  u_char *pnt;
-  
-  if (len == 0)
-    return;
-
-  pnt = (u_char *) addr;
-
-  for (i = 0; i < len; i++)
-    oid[i] = *pnt++;
-}
-
-int
-oid_compare (oid *o1, int o1_len, oid *o2, int o2_len)
-{
-  int i;
-
-  for (i = 0; i < min (o1_len, o2_len); i++)
-    {
-      if (o1[i] < o2[i])
-       return -1;
-      else if (o1[i] > o2[i])
-       return 1;
-    }
-  if (o1_len < o2_len)
-    return -1;
-  if (o1_len > o2_len)
-    return 1;
+static struct thread_master *smux_master;
 
-  return 0;
-}
-
-int
+static int
 oid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len)
 {
   int i;
@@ -158,9 +131,9 @@ oid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len)
 
   return 0;
 }
-\f
-void
-smux_oid_dump (const char *prefix, oid *oid, size_t oid_len)
+
+static void
+smux_oid_dump (const char *prefix, const oid *oid, size_t oid_len)
 {
   unsigned int i;
   int first = 1;
@@ -173,23 +146,17 @@ smux_oid_dump (const char *prefix, oid *oid, size_t oid_len)
       sprintf (buf + strlen (buf), "%s%d", first ? "" : ".", (int) oid[i]);
       first = 0;
     }
-  zlog_info ("%s: %s", prefix, buf);
+  zlog_debug ("%s: %s", prefix, buf);
 }
 
-int
-smux_socket ()
+static int
+smux_socket (void)
 {
   int ret;
-#ifdef HAVE_IPV6
   struct addrinfo hints, *res0, *res;
   int gai;
-#else
-  struct sockaddr_in serv;
-  struct servent *sp;
-#endif
   int sock = 0;
 
-#ifdef HAVE_IPV6
   memset(&hints, 0, sizeof(hints));
   hints.ai_family = PF_UNSPEC;
   hints.ai_socktype = SOCK_STREAM;
@@ -209,9 +176,7 @@ smux_socket ()
   for(res=res0; res; res=res->ai_next)
     {
       if (res->ai_family != AF_INET 
-#ifdef HAVE_IPV6
          && res->ai_family != AF_INET6
-#endif /* HAVE_IPV6 */
          )
        continue;
 
@@ -232,51 +197,16 @@ smux_socket ()
   freeaddrinfo(res0);
   if (sock < 0)
     zlog_warn ("Can't connect to SNMP agent with SMUX");
-#else
-  sock = socket (AF_INET, SOCK_STREAM, 0);
-  if (sock < 0)
-    {
-      zlog_warn ("Can't make socket for SNMP");
-      return -1;
-    }
-
-  memset (&serv, 0, sizeof (struct sockaddr_in));
-  serv.sin_family = AF_INET;
-#ifdef HAVE_SIN_LEN
-  serv.sin_len = sizeof (struct sockaddr_in);
-#endif /* HAVE_SIN_LEN */
-
-  sp = getservbyname ("smux", "tcp");
-  if (sp != NULL) 
-    serv.sin_port = sp->s_port;
-  else
-    serv.sin_port = htons (SMUX_PORT_DEFAULT);
-
-  serv.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
-
-  sockopt_reuseaddr (sock);
-  sockopt_reuseport (sock);
-
-  ret = connect (sock, (struct sockaddr *) &serv, sizeof (struct sockaddr_in));
-  if (ret < 0)
-    {
-      close (sock);
-      smux_sock = -1;
-      zlog_warn ("Can't connect to SNMP agent with SMUX");
-      return -1;
-    }
-#endif
   return sock;
 }
 
-void
+static void
 smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,
                   long errindex, u_char val_type, void *arg, size_t arg_len)
 {
-  int ret;
   u_char buf[BUFSIZ];
   u_char *ptr, *h1, *h1e, *h2, *h2e;
-  int len, length;
+  size_t len, length;
 
   ptr = buf;
   len = BUFSIZ;
@@ -284,8 +214,8 @@ smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,
 
   if (debug_smux)
     {
-      zlog_info ("SMUX GETRSP send");
-      zlog_info ("SMUX GETRSP reqid: %ld", reqid);
+      zlog_debug ("SMUX GETRSP send");
+      zlog_debug ("SMUX GETRSP reqid: %ld", reqid);
     }
 
   h1 = ptr;
@@ -298,13 +228,13 @@ smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,
                       &reqid, sizeof (reqid));
 
   if (debug_smux)
-    zlog_info ("SMUX GETRSP errstat: %ld", errstat);
+    zlog_debug ("SMUX GETRSP errstat: %ld", errstat);
 
   ptr = asn_build_int (ptr, &len,
                       (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
                       &errstat, sizeof (errstat));
   if (debug_smux)
-    zlog_info ("SMUX GETRSP errindex: %ld", errindex);
+    zlog_debug ("SMUX GETRSP errindex: %ld", errindex);
 
   ptr = asn_build_int (ptr, &len,
                       (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
@@ -327,13 +257,13 @@ smux_getresp_send (oid objid[], size_t objid_len, long reqid, long errstat,
   asn_build_sequence(h1,&length,(u_char)SMUX_GETRSP,ptr-h1e);
 
   if (debug_smux)
-    zlog_info ("SMUX getresp send: %d", ptr - buf);
+    zlog_debug ("SMUX getresp send: %td", (ptr - buf));
   
-  ret = send (smux_sock, buf, (ptr - buf), 0);
+  send (smux_sock, buf, (ptr - buf), 0);
 }
 
-char *
-smux_var (char *ptr, int len, oid objid[], size_t *objid_len,
+static u_char *
+smux_var (u_char *ptr, size_t len, oid objid[], size_t *objid_len,
           size_t *var_val_len,
           u_char *var_val_type,
           void **var_value)
@@ -344,15 +274,15 @@ smux_var (char *ptr, int len, oid objid[], size_t *objid_len,
   u_char *val;
 
   if (debug_smux)
-    zlog_info ("SMUX var parse: len %d", len);
+    zlog_debug ("SMUX var parse: len %zd", len);
 
   /* Parse header. */
   ptr = asn_parse_header (ptr, &len, &type);
   
   if (debug_smux)
     {
-      zlog_info ("SMUX var parse: type %d len %d", type, len);
-      zlog_info ("SMUX var parse: type must be %d", 
+      zlog_debug ("SMUX var parse: type %d len %zd", type, len);
+      zlog_debug ("SMUX var parse: type must be %d", 
                 (ASN_SEQUENCE | ASN_CONSTRUCTOR));
     }
 
@@ -375,7 +305,7 @@ smux_var (char *ptr, int len, oid objid[], size_t *objid_len,
     smux_oid_dump ("Request OID", objid, *objid_len);
 
   if (debug_smux)
-    zlog_info ("SMUX val_type: %d", val_type);
+    zlog_debug ("SMUX val_type: %d", val_type);
 
   /* Check request value type. */
   if (debug_smux)
@@ -384,46 +314,46 @@ smux_var (char *ptr, int len, oid objid[], size_t *objid_len,
     case ASN_NULL:
       /* In case of SMUX_GET or SMUX_GET_NEXT val_type is set to
          ASN_NULL. */
-      zlog_info ("ASN_NULL");
+      zlog_debug ("ASN_NULL");
       break;
 
     case ASN_INTEGER:
-      zlog_info ("ASN_INTEGER");
+      zlog_debug ("ASN_INTEGER");
       break;
     case ASN_COUNTER:
     case ASN_GAUGE:
     case ASN_TIMETICKS:
     case ASN_UINTEGER:
-      zlog_info ("ASN_COUNTER");
+      zlog_debug ("ASN_COUNTER");
       break;
     case ASN_COUNTER64:
-      zlog_info ("ASN_COUNTER64");
+      zlog_debug ("ASN_COUNTER64");
       break;
     case ASN_IPADDRESS:
-      zlog_info ("ASN_IPADDRESS");
+      zlog_debug ("ASN_IPADDRESS");
       break;
     case ASN_OCTET_STR:
-      zlog_info ("ASN_OCTET_STR");
+      zlog_debug ("ASN_OCTET_STR");
       break;
     case ASN_OPAQUE:
     case ASN_NSAP:
     case ASN_OBJECT_ID:
-      zlog_info ("ASN_OPAQUE");
+      zlog_debug ("ASN_OPAQUE");
       break;
     case SNMP_NOSUCHOBJECT:
-      zlog_info ("SNMP_NOSUCHOBJECT");
+      zlog_debug ("SNMP_NOSUCHOBJECT");
       break;
     case SNMP_NOSUCHINSTANCE:
-      zlog_info ("SNMP_NOSUCHINSTANCE");
+      zlog_debug ("SNMP_NOSUCHINSTANCE");
       break;
     case SNMP_ENDOFMIBVIEW:
-      zlog_info ("SNMP_ENDOFMIBVIEW");
+      zlog_debug ("SNMP_ENDOFMIBVIEW");
       break;
     case ASN_BIT_STR:
-      zlog_info ("ASN_BIT_STR");
+      zlog_debug ("ASN_BIT_STR");
       break;
     default:
-      zlog_info ("Unknown type");
+      zlog_debug ("Unknown type");
       break;
     }
   return ptr;
@@ -433,7 +363,7 @@ smux_var (char *ptr, int len, oid objid[], size_t *objid_len,
    ucd-snmp smux and as such suppose, that the peer receives in the message
    only one variable. Fortunately, IBM seems to do the same in AIX. */
 
-int
+static int
 smux_set (oid *reqid, size_t *reqid_len,
           u_char val_type, void *val, size_t val_len, int action)
 {
@@ -442,16 +372,15 @@ smux_set (oid *reqid, size_t *reqid_len,
   struct variable *v;
   int subresult;
   oid *suffix;
-  int suffix_len;
+  size_t suffix_len;
   int result;
   u_char *statP = NULL;
   WriteMethod *write_method = NULL;
-  struct listnode *node;
+  struct listnode *node, *nnode;
 
   /* Check */
-  for (node = treelist->head; node; node = node->next)
+  for (ALL_LIST_ELEMENTS (treelist, node, nnode, subtree))
     {
-      subtree = node->data;
       subresult = oid_compare_part (reqid, *reqid_len,
                                     subtree->name, subtree->name_len);
 
@@ -476,7 +405,7 @@ smux_set (oid *reqid, size_t *reqid_len,
               if (result == 0)
                 {
                   if (debug_smux)
-                    zlog_info ("SMUX function call index is %d", v->magic);
+                    zlog_debug ("SMUX function call index is %d", v->magic);
                  
                   statP = (*v->findVar) (v, suffix, &suffix_len, 1,
                                         &val_len, &write_method);
@@ -484,7 +413,7 @@ smux_set (oid *reqid, size_t *reqid_len,
                   if (write_method)
                     {
                       return (*write_method)(action, val, val_type, val_len,
-                                            statP, suffix, suffix_len, v);
+                                            statP, suffix, suffix_len);
                     }
                   else
                     {
@@ -502,7 +431,7 @@ smux_set (oid *reqid, size_t *reqid_len,
   return SNMP_ERR_NOSUCHNAME;
 }
 
-int
+static int
 smux_get (oid *reqid, size_t *reqid_len, int exact, 
          u_char *val_type,void **val, size_t *val_len)
 {
@@ -511,15 +440,14 @@ smux_get (oid *reqid, size_t *reqid_len, int exact,
   struct variable *v;
   int subresult;
   oid *suffix;
-  int suffix_len;
+  size_t suffix_len;
   int result;
   WriteMethod *write_method=NULL;
-  struct listnode *node;
+  struct listnode *node, *nnode;
 
   /* Check */
-  for (node = treelist->head; node; node = node->next)
+  for (ALL_LIST_ELEMENTS (treelist, node, nnode,subtree))
     {
-      subtree = node->data;
       subresult = oid_compare_part (reqid, *reqid_len, 
                                    subtree->name, subtree->name_len);
 
@@ -544,7 +472,7 @@ smux_get (oid *reqid, size_t *reqid_len, int exact,
              if (result == 0)
                {
                  if (debug_smux)
-                   zlog_info ("SMUX function call index is %d", v->magic);
+                   zlog_debug ("SMUX function call index is %d", v->magic);
 
                  *val = (*v->findVar) (v, suffix, &suffix_len, exact,
                                        val_len, &write_method);
@@ -569,7 +497,7 @@ smux_get (oid *reqid, size_t *reqid_len, int exact,
   return SNMP_ERR_NOSUCHNAME;
 }
 
-int
+static int
 smux_getnext (oid *reqid, size_t *reqid_len, int exact, 
              u_char *val_type,void **val, size_t *val_len)
 {
@@ -580,10 +508,10 @@ smux_getnext (oid *reqid, size_t *reqid_len, int exact,
   struct variable *v;
   int subresult;
   oid *suffix;
-  int suffix_len;
+  size_t suffix_len;
   int result;
   WriteMethod *write_method=NULL;
-  struct listnode *node;
+  struct listnode *node, *nnode;
 
 
   /* Save incoming request. */
@@ -591,9 +519,8 @@ smux_getnext (oid *reqid, size_t *reqid_len, int exact,
   savelen = *reqid_len;
 
   /* Check */
-  for (node = treelist->head; node; node = node->next)
+  for (ALL_LIST_ELEMENTS (treelist, node, nnode, subtree))
     {
-      subtree = node->data;
       subresult = oid_compare_part (reqid, *reqid_len, 
                                    subtree->name, subtree->name_len);
 
@@ -631,7 +558,7 @@ smux_getnext (oid *reqid, size_t *reqid_len, int exact,
              if (result <= 0)
                {
                  if (debug_smux)
-                   zlog_info ("SMUX function call index is %d", v->magic);
+                   zlog_debug ("SMUX function call index is %d", v->magic);
                  if(result<0)
                    {
                      oid_copy(suffix, v->name, v->namelen);
@@ -656,8 +583,8 @@ smux_getnext (oid *reqid, size_t *reqid_len, int exact,
 }
 
 /* GET message header. */
-char *
-smux_parse_get_header (char *ptr, size_t *len, long *reqid)
+static u_char *
+smux_parse_get_header (u_char *ptr, size_t *len, long *reqid)
 {
   u_char type;
   long errstat;
@@ -667,25 +594,25 @@ smux_parse_get_header (char *ptr, size_t *len, long *reqid)
   ptr = asn_parse_int (ptr, len, &type, reqid, sizeof (*reqid));
 
   if (debug_smux)
-    zlog_info ("SMUX GET reqid: %d len: %d", (int) *reqid, (int) *len);
+    zlog_debug ("SMUX GET reqid: %d len: %d", (int) *reqid, (int) *len);
 
   /* Error status. */
   ptr = asn_parse_int (ptr, len, &type, &errstat, sizeof (errstat));
 
   if (debug_smux)
-    zlog_info ("SMUX GET errstat %ld len: %d", errstat, *len);
+    zlog_debug ("SMUX GET errstat %ld len: %zd", errstat, *len);
 
   /* Error index. */
   ptr = asn_parse_int (ptr, len, &type, &errindex, sizeof (errindex));
 
   if (debug_smux)
-    zlog_info ("SMUX GET errindex %ld len: %d", errindex, *len);
+    zlog_debug ("SMUX GET errindex %ld len: %zd", errindex, *len);
 
   return ptr;
 }
 
-void
-smux_parse_set (char *ptr, size_t len, int action)
+static void
+smux_parse_set (u_char *ptr, size_t len, int action)
 {
   long reqid;
   oid oid[MAX_OID_LEN];
@@ -696,7 +623,7 @@ smux_parse_set (char *ptr, size_t len, int action)
   int ret;
 
   if (debug_smux)
-    zlog_info ("SMUX SET(%s) message parse: len %d",
+    zlog_debug ("SMUX SET(%s) message parse: len %zd",
                (RESERVE1 == action) ? "RESERVE1" : ((FREE == action) ? "FREE" : "COMMIT"),
                len);
 
@@ -708,15 +635,15 @@ smux_parse_set (char *ptr, size_t len, int action)
 
   ret = smux_set (oid, &oid_len, val_type, val, val_len, action);
   if (debug_smux)
-    zlog_info ("SMUX SET ret %d", ret);
+    zlog_debug ("SMUX SET ret %d", ret);
 
   /* Return result. */
   if (RESERVE1 == action)
     smux_getresp_send (oid, oid_len, reqid, ret, 3, ASN_NULL, NULL, 0);
 }
 
-void
-smux_parse_get (char *ptr, size_t len, int exact)
+static void
+smux_parse_get (u_char *ptr, size_t len, int exact)
 {
   long reqid;
   oid oid[MAX_OID_LEN];
@@ -727,7 +654,7 @@ smux_parse_get (char *ptr, size_t len, int exact)
   int ret;
 
   if (debug_smux)
-    zlog_info ("SMUX GET message parse: len %d", len);
+    zlog_debug ("SMUX GET message parse: len %zd", len);
   
   /* Parse GET message header. */
   ptr = smux_parse_get_header (ptr, &len, &reqid);
@@ -749,8 +676,8 @@ smux_parse_get (char *ptr, size_t len, int exact)
 }
 
 /* Parse SMUX_CLOSE message. */
-void
-smux_parse_close (char *ptr, int len)
+static void
+smux_parse_close (u_char *ptr, int len)
 {
   long reason = 0;
 
@@ -763,21 +690,21 @@ smux_parse_close (char *ptr, int len)
 }
 
 /* SMUX_RRSP message. */
-void
-smux_parse_rrsp (char *ptr, int len)
+static void
+smux_parse_rrsp (u_char *ptr, size_t len)
 {
-  char val;
+  u_char val;
   long errstat;
   
   ptr = asn_parse_int (ptr, &len, &val, &errstat, sizeof (errstat));
 
   if (debug_smux)
-    zlog_info ("SMUX_RRSP value: %d errstat: %ld", val, errstat);
+    zlog_debug ("SMUX_RRSP value: %d errstat: %ld", val, errstat);
 }
 
 /* Parse SMUX message. */
-int
-smux_parse (char *ptr, int len)
+static int
+smux_parse (u_char *ptr, size_t len)
 {
   /* This buffer we'll use for SOUT message. We could allocate it with
      malloc and save only static pointer/lenght, but IMHO static
@@ -797,7 +724,7 @@ process_rest: /* see note below: YYY */
   ptr = asn_parse_header (ptr, &len, &type);
 
   if (debug_smux)
-    zlog_info ("SMUX message received type: %d rest len: %d", type, len);
+    zlog_debug ("SMUX message received type: %d rest len: %zd", type, len);
 
   switch (type)
     {
@@ -814,7 +741,7 @@ process_rest: /* see note below: YYY */
     case SMUX_SOUT:
       /* SMUX_SOUT message is now valied for us. */
       if (debug_smux)
-        zlog_info ("SMUX_SOUT(%s)", rollback ? "rollback" : "commit");
+        zlog_debug ("SMUX_SOUT(%s)", rollback ? "rollback" : "commit");
 
       if (sout_save_len > 0)
         {
@@ -849,32 +776,32 @@ process_rest: /* see note below: YYY */
     case SMUX_CLOSE:
       /* Close SMUX connection. */
       if (debug_smux)
-       zlog_info ("SMUX_CLOSE");
+       zlog_debug ("SMUX_CLOSE");
       smux_parse_close (ptr, len);
       return -1;
       break;
     case SMUX_RRSP:
       /* This is response for register message. */
       if (debug_smux)
-       zlog_info ("SMUX_RRSP");
+       zlog_debug ("SMUX_RRSP");
       smux_parse_rrsp (ptr, len);
       break;
     case SMUX_GET:
       /* Exact request for object id. */
       if (debug_smux)
-       zlog_info ("SMUX_GET");
+       zlog_debug ("SMUX_GET");
       smux_parse_get (ptr, len, 1);
       break;
     case SMUX_GETNEXT:
       /* Next request for object id. */
       if (debug_smux)
-       zlog_info ("SMUX_GETNEXT");
+       zlog_debug ("SMUX_GETNEXT");
       smux_parse_get (ptr, len, 0);
       break;
     case SMUX_SET:
       /* SMUX_SET is supported with some limitations. */
       if (debug_smux)
-       zlog_info ("SMUX_SET");
+       zlog_debug ("SMUX_SET");
 
       /* save the data for future SMUX_SOUT */
       memcpy (sout_save_buff, ptr, len);
@@ -889,7 +816,7 @@ process_rest: /* see note below: YYY */
 }
 
 /* SMUX message read function. */
-int
+static int
 smux_read (struct thread *t)
 {
   int sock;
@@ -902,14 +829,14 @@ smux_read (struct thread *t)
   smux_read_thread = NULL;
 
   if (debug_smux)
-    zlog_info ("SMUX read start");
+    zlog_debug ("SMUX read start");
 
   /* Read message from SMUX socket. */
   len = recv (sock, buf, SMUXMAXPKTSIZE, 0);
 
   if (len < 0)
     {
-      zlog_warn ("Can't read all SMUX packet: %s", strerror (errno));
+      zlog_warn ("Can't read all SMUX packet: %s", safe_strerror (errno));
       close (sock);
       smux_sock = -1;
       smux_event (SMUX_CONNECT, 0);
@@ -926,7 +853,7 @@ smux_read (struct thread *t)
     }
 
   if (debug_smux)
-    zlog_info ("SMUX read len: %d", len);
+    zlog_debug ("SMUX read len: %d", len);
 
   /* Parse the message. */
   ret = smux_parse (buf, len);
@@ -945,20 +872,20 @@ smux_read (struct thread *t)
   return 0;
 }
 
-int
+static int
 smux_open (int sock)
 {
   u_char buf[BUFSIZ];
   u_char *ptr;
-  int len;
-  u_long version;
-  u_char progname[] = QUAGGA_PROGNAME "-" QUAGGA_VERSION;
+  size_t len;
+  long version;
+  const char progname[] = FRR_SMUX_NAME "-" FRR_VERSION;
 
   if (debug_smux)
     {
       smux_oid_dump ("SMUX open oid", smux_oid, smux_oid_len);
-      zlog_info ("SMUX open progname: %s", progname);
-      zlog_info ("SMUX open password: %s", smux_passwd);
+      zlog_debug ("SMUX open progname: %s", progname);
+      zlog_debug ("SMUX open password: %s", smux_passwd);
     }
 
   ptr = buf;
@@ -971,7 +898,7 @@ smux_open (int sock)
   version = 0;
   ptr = asn_build_int (ptr, &len, 
                       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-                      &version, sizeof (u_long));
+                      &version, sizeof (version));
 
   /* SMUX connection oid. */
   ptr = asn_build_objid (ptr, &len,
@@ -983,13 +910,13 @@ smux_open (int sock)
   ptr = asn_build_string (ptr, &len, 
                          (u_char)
                          (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
-                         progname, strlen (progname));
+                         (const u_char *) progname, strlen (progname));
 
   /* SMUX connection password. */
   ptr = asn_build_string (ptr, &len, 
                          (u_char)
                          (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OCTET_STR),
-                         smux_passwd, strlen (smux_passwd));
+                         (u_char *)smux_passwd, strlen (smux_passwd));
 
   /* Fill in real SMUX header.  We exclude ASN header size (2). */
   len = BUFSIZ;
@@ -998,16 +925,23 @@ smux_open (int sock)
   return send (sock, buf, (ptr - buf), 0);
 }
 
+/* `ename` is ignored. Instead of using the provided enterprise OID,
+   the SMUX peer is used. This keep compatibility with the previous
+   versions of Quagga.
+
+   All other fields are used as they are intended. */
 int
-smux_trap (oid *name, size_t namelen,
-          oid *iname, size_t inamelen,
-          struct trap_object *trapobj, size_t trapobjlen,
-          unsigned int tick, u_char sptrap)
+smux_trap (struct variable *vp, size_t vp_len,
+          const oid *ename, size_t enamelen,
+          const oid *name, size_t namelen,
+          const oid *iname, size_t inamelen,
+          const struct trap_object *trapobj, size_t trapobjlen,
+          u_char sptrap)
 {
   unsigned int i;
   u_char buf[BUFSIZ];
   u_char *ptr;
-  int len, length;
+  size_t len, length;
   struct in_addr addr;
   unsigned long val;
   u_char *h1, *h1e;
@@ -1034,25 +968,25 @@ smux_trap (oid *name, size_t namelen,
   ptr = asn_build_string (ptr, &len, 
                          (u_char)
                          (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_IPADDRESS),
-                         (u_char *)&addr, sizeof (struct in_addr));
+                         (u_char *)&addr, sizeof (addr));
 
   /* Generic trap integer. */
   val = SNMP_TRAP_ENTERPRISESPECIFIC;
   ptr = asn_build_int (ptr, &len, 
                       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-                      &val, sizeof (int));
+                      (long *)&val, sizeof (val));
 
   /* Specific trap integer. */
   val = sptrap;
   ptr = asn_build_int (ptr, &len, 
                       (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-                      &val, sizeof (int));
+                      (long *)&val, sizeof (val));
 
   /* Timeticks timestamp. */
   val = 0;
   ptr = asn_build_unsigned_int (ptr, &len, 
                                (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_TIMETICKS),
-                               &val, sizeof (int));
+                               &val, sizeof (val));
   
   /* Variables. */
   h1 = ptr;
@@ -1073,18 +1007,39 @@ smux_trap (oid *name, size_t namelen,
       u_char val_type;
 
       /* Make OID. */
-      oid_copy (oid, name, namelen);
-      oid_copy (oid + namelen, trapobj[i].name, trapobj[i].namelen);
-      oid_copy (oid + namelen + trapobj[i].namelen, iname, inamelen);
-      oid_len = namelen + trapobj[i].namelen + inamelen;
+      if (trapobj[i].namelen > 0) 
+        {
+          oid_copy (oid, name, namelen);
+          oid_copy (oid + namelen, trapobj[i].name, trapobj[i].namelen);
+          oid_copy (oid + namelen + trapobj[i].namelen, iname, inamelen);
+          oid_len = namelen + trapobj[i].namelen + inamelen;
+        }
+      else 
+        {
+          oid_copy (oid, name, namelen);
+          oid_copy (oid + namelen, trapobj[i].name, trapobj[i].namelen * (-1));
+          oid_len = namelen + trapobj[i].namelen * (-1) ;
+        }
 
-      if (debug_smux)
-       smux_oid_dump ("Trap", oid, oid_len);
+      if (debug_smux) 
+        {
+          smux_oid_dump ("Trap", name, namelen);
+          if (trapobj[i].namelen < 0)
+            smux_oid_dump ("Trap", 
+                           trapobj[i].name, (- 1) * (trapobj[i].namelen));
+          else 
+            {
+              smux_oid_dump ("Trap", trapobj[i].name, (trapobj[i].namelen));
+              smux_oid_dump ("Trap", iname, inamelen);
+            }
+          smux_oid_dump ("Trap", oid, oid_len);
+          zlog_info ("BUFSIZ: %d // oid_len: %lu", BUFSIZ, (u_long)oid_len);
+      }
 
       ret = smux_get (oid, &oid_len, 1, &val_type, &val, &val_len);
 
       if (debug_smux)
-       zlog_info ("smux_get result %d", ret);
+       zlog_debug ("smux_get result %d", ret);
 
       if (ret == 0)
        ptr = snmp_build_var_op (ptr, oid, &oid_len,
@@ -1103,26 +1058,25 @@ smux_trap (oid *name, size_t namelen,
   return send (smux_sock, buf, (ptr - buf), 0);
 }
 
-int
+static int
 smux_register (int sock)
 {
   u_char buf[BUFSIZ];
   u_char *ptr;
-  int len, ret;
+  int ret;
+  size_t len;
   long priority;
   long operation;
   struct subtree *subtree;
-  struct listnode *node;
+  struct listnode *node, *nnode;
 
   ret = 0;
 
-  for (node = treelist->head; node; node = node->next)
+  for (ALL_LIST_ELEMENTS (treelist, node, nnode, subtree))
     {
       ptr = buf;
       len = BUFSIZ;
 
-      subtree = node->data;
-
       /* SMUX RReq Header. */
       ptr = asn_build_header (ptr, &len, (u_char) SMUX_RREQ, 0);
 
@@ -1136,19 +1090,19 @@ smux_register (int sock)
       priority = -1;
       ptr = asn_build_int (ptr, &len, 
                          (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-                         &priority, sizeof (u_long));
+                         &priority, sizeof (priority));
 
       /* Operation. */
       operation = 2; /* Register R/W */
       ptr = asn_build_int (ptr, &len, 
                          (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER),
-                         &operation, sizeof (u_long));
+                         &operation, sizeof (operation));
 
       if (debug_smux)
         {
           smux_oid_dump ("SMUX register oid", subtree->name, subtree->name_len);
-          zlog_info ("SMUX register priority: %ld", priority);
-          zlog_info ("SMUX register operation: %ld", operation);
+          zlog_debug ("SMUX register priority: %ld", priority);
+          zlog_debug ("SMUX register operation: %ld", operation);
         }
 
       len = BUFSIZ;
@@ -1161,13 +1115,13 @@ smux_register (int sock)
 }
 
 /* Try to connect to SNMP agent. */
-int
+static int
 smux_connect (struct thread *t)
 {
   int ret;
 
   if (debug_smux)
-    zlog_info ("SMUX connect try %d", fail + 1);
+    zlog_debug ("SMUX connect try %d", fail + 1);
 
   /* Clear thread poner of myself. */
   smux_connect_thread = NULL;
@@ -1185,7 +1139,7 @@ smux_connect (struct thread *t)
   ret = smux_open (smux_sock);
   if (ret < 0)
     {
-      zlog_warn ("SMUX open message send failed: %s", strerror (errno));
+      zlog_warn ("SMUX open message send failed: %s", safe_strerror (errno));
       close (smux_sock);
       smux_sock = -1;
       if (++fail < SMUX_MAX_FAILURE)
@@ -1197,7 +1151,7 @@ smux_connect (struct thread *t)
   ret = smux_register (smux_sock);
   if (ret < 0)
     {
-      zlog_warn ("SMUX register message send failed: %s", strerror (errno));
+      zlog_warn ("SMUX register message send failed: %s", safe_strerror (errno));
       close (smux_sock);
       smux_sock = -1;
       if (++fail < SMUX_MAX_FAILURE)
@@ -1212,13 +1166,20 @@ smux_connect (struct thread *t)
 }
 
 /* Clear all SMUX related resources. */
-void
-smux_stop ()
+static void
+smux_stop (void)
 {
   if (smux_read_thread)
-    thread_cancel (smux_read_thread);
+    {
+      thread_cancel (smux_read_thread);
+      smux_read_thread = NULL;
+    }
+
   if (smux_connect_thread)
-    thread_cancel (smux_connect_thread);
+    {
+      thread_cancel (smux_connect_thread);
+      smux_connect_thread = NULL;
+    }
 
   if (smux_sock >= 0)
     {
@@ -1226,7 +1187,7 @@ smux_stop ()
       smux_sock = -1;
     }
 }
-\f
+
 
 
 void
@@ -1235,20 +1196,25 @@ smux_event (enum smux_event event, int sock)
   switch (event)
     {
     case SMUX_SCHEDULE:
-      smux_connect_thread = thread_add_event (master, smux_connect, NULL, 0);
+      smux_connect_thread = NULL;
+      thread_add_event(smux_master, smux_connect, NULL, 0,
+                       &smux_connect_thread);
       break;
     case SMUX_CONNECT:
-      smux_connect_thread = thread_add_timer (master, smux_connect, NULL, 10);
+      smux_connect_thread = NULL;
+      thread_add_timer(smux_master, smux_connect, NULL, 10,
+                       &smux_connect_thread);
       break;
     case SMUX_READ:
-      smux_read_thread = thread_add_read (master, smux_read, NULL, sock);
+      smux_read_thread = NULL;
+      thread_add_read(smux_master, smux_read, NULL, sock, &smux_read_thread);
       break;
     default:
       break;
     }
 }
-\f
-int
+
+static int
 smux_str2oid (const char *str, oid *oid, size_t *oid_len)
 {
   int len;
@@ -1291,7 +1257,7 @@ smux_str2oid (const char *str, oid *oid, size_t *oid_len)
   return 0;
 }
 
-oid *
+static oid *
 smux_oid_dup (oid *objid, size_t objid_len)
 {
   oid *new;
@@ -1302,7 +1268,7 @@ smux_oid_dup (oid *objid, size_t objid_len)
   return new;
 }
 
-int
+static int
 smux_peer_oid (struct vty *vty, const char *oid_str, const char *passwd_str)
 {
   int ret;
@@ -1316,11 +1282,14 @@ smux_peer_oid (struct vty *vty, const char *oid_str, const char *passwd_str)
       return CMD_WARNING;
     }
 
-  if (smux_oid && smux_oid != smux_default_oid)
-    free (smux_oid);
+  if (smux_oid)
+    {
+      free (smux_oid);
+      smux_oid = NULL;
+    }
 
   /* careful, smux_passwd might point to string constant */
-  if (smux_passwd && smux_passwd != smux_default_passwd)
+  if (smux_passwd)
     {
       free (smux_passwd);
       smux_passwd = NULL;
@@ -1331,52 +1300,28 @@ smux_peer_oid (struct vty *vty, const char *oid_str, const char *passwd_str)
 
   if (passwd_str)
     smux_passwd = strdup (passwd_str);
+  else
+    smux_passwd = strdup ("");
 
-  return CMD_SUCCESS;
-}
-
-int
-smux_header_generic (struct variable *v, oid *name, size_t *length, int exact,
-                    size_t *var_len, WriteMethod **write_method)
-{
-  oid fulloid[MAX_OID_LEN];
-  int ret;
-
-  oid_copy (fulloid, v->name, v->namelen);
-  fulloid[v->namelen] = 0;
-  /* Check against full instance. */
-  ret = oid_compare (name, *length, fulloid, v->namelen + 1);
-
-  /* Check single instance. */
-  if ((exact && (ret != 0)) || (!exact && (ret >= 0)))
-       return MATCH_FAILED;
-
-  /* In case of getnext, fill in full instance. */
-  memcpy (name, fulloid, (v->namelen + 1) * sizeof (oid));
-  *length = v->namelen + 1;
-
-  *write_method = 0;
-  *var_len = sizeof(long);    /* default to 'long' results */
-
-  return MATCH_SUCCEEDED;
+  return 0;
 }
 
-int
-smux_peer_default ()
+static int
+smux_peer_default (void)
 {
-  if (smux_oid != smux_default_oid)
+  if (smux_oid)
     {
       free (smux_oid);
-      smux_oid = smux_default_oid;
-      smux_oid_len = smux_default_oid_len;
+      smux_oid = NULL;
     }
   
   /* careful, smux_passwd might be pointing at string constant */
-  if (smux_passwd != smux_default_passwd)
+  if (smux_passwd)
     {
       free (smux_passwd);
-      smux_passwd = (char *)smux_default_passwd;
+      smux_passwd = NULL;
     }
+
   return CMD_SUCCESS;
 }
 
@@ -1387,7 +1332,14 @@ DEFUN (smux_peer,
        "SNMP MUX peer settings\n"
        "Object ID used in SMUX peering\n")
 {
-  return smux_peer_oid (vty, argv[0], NULL);
+  int idx_oid = 2;
+  if (smux_peer_oid (vty, argv[idx_oid]->arg, NULL) == 0)
+    {
+      smux_start();
+      return CMD_SUCCESS;
+    }
+  else
+    return CMD_WARNING;
 }
 
 DEFUN (smux_peer_password,
@@ -1398,39 +1350,36 @@ DEFUN (smux_peer_password,
        "SMUX peering object ID\n"
        "SMUX peering password\n")
 {
-  return smux_peer_oid (vty, argv[0], argv[1]);
+  int idx_oid = 2;
+  if (smux_peer_oid (vty, argv[idx_oid]->arg, argv[3]->rg) == 0)
+    {
+      smux_start();
+      return CMD_SUCCESS;
+    }
+  else
+    return CMD_WARNING;
 }
 
 DEFUN (no_smux_peer,
        no_smux_peer_cmd,
-       "no smux peer OID",
-       NO_STR
-       "SNMP MUX protocol settings\n"
-       "SNMP MUX peer settings\n"
-       "Object ID used in SMUX peering\n")
-{
-  return smux_peer_default ();
-}
-
-DEFUN (no_smux_peer_password,
-       no_smux_peer_password_cmd,
-       "no smux peer OID PASSWORD",
+       "no smux peer [OID [PASSWORD]]",
        NO_STR
        "SNMP MUX protocol settings\n"
        "SNMP MUX peer settings\n"
        "SMUX peering object ID\n"
        "SMUX peering password\n")
 {
+  smux_stop();
   return smux_peer_default ();
 }
 
-int
+static int
 config_write_smux (struct vty *vty)
 {
   int first = 1;
   unsigned int i;
 
-  if (smux_oid != smux_default_oid || smux_passwd != smux_default_passwd)
+  if (smux_oid)
     {
       vty_out (vty, "smux peer ");
       for (i = 0; i < smux_oid_len; i++)
@@ -1461,13 +1410,6 @@ smux_register_mib (const char *descr, struct variable *var,
   listnode_add_sort(treelist, tree);
 }
 
-void
-smux_reset ()
-{
-  /* Setting configuration to default. */
-  smux_peer_default ();
-}
-
 /* Compare function to keep treelist sorted */
 static int
 smux_tree_cmp(struct subtree *tree1, struct subtree *tree2)
@@ -1478,20 +1420,11 @@ smux_tree_cmp(struct subtree *tree1, struct subtree *tree2)
 
 /* Initialize some values then schedule first SMUX connection. */
 void
-smux_init (struct thread_master *tm, oid defoid[], size_t defoid_len)
+smux_init (struct thread_master *tm)
 {
-  /* Set default SMUX oid. */
-  smux_default_oid = defoid;
-  smux_default_oid_len = defoid_len;
-
-  smux_oid = smux_default_oid;
-  smux_oid_len = smux_default_oid_len;
-
-  /* be careful with smux_passwd, points to string constant by default */
-  smux_passwd = (char *)smux_default_passwd;
-
+  assert (tm);
   /* copy callers thread master */
-  master = tm;
+  smux_master = tm;
   
   /* Make MIB tree. */
   treelist = list_new();
@@ -1503,13 +1436,17 @@ smux_init (struct thread_master *tm, oid defoid[], size_t defoid_len)
   install_element (CONFIG_NODE, &smux_peer_cmd);
   install_element (CONFIG_NODE, &smux_peer_password_cmd);
   install_element (CONFIG_NODE, &no_smux_peer_cmd);
-  install_element (CONFIG_NODE, &no_smux_peer_password_cmd);
+  install_element (CONFIG_NODE, &no_smux_peer_oid_cmd);
+  install_element (CONFIG_NODE, &no_smux_peer_oid_password_cmd);
 }
 
 void
 smux_start(void)
 {
+  /* Close any existing connections. */
+  smux_stop();
+
   /* Schedule first connection. */
   smux_event (SMUX_SCHEDULE, 0);
 }
-#endif /* HAVE_SNMP */
+#endif /* SNMP_SMUX */