* 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>
#include <net-snmp/net-snmp-includes.h>
-#else
-#include <asn1.h>
-#include <snmp.h>
-#include <snmp_impl.h>
-#endif
#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;
};
/* thread master */
-static struct thread_master *master;
-\f
-void *
-oid_copy (void *dest, const 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;
-
- return 0;
-}
+static struct thread_master *smux_master;
static int
oid_compare_part (oid *o1, int o1_len, oid *o2, int o2_len)
return 0;
}
-\f
+
static void
smux_oid_dump (const char *prefix, const oid *oid, size_t oid_len)
{
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;
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;
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_STRUCT_SOCKADDR_IN_SIN_LEN
- serv.sin_len = sizeof (struct sockaddr_in);
-#endif /* HAVE_STRUCT_SOCKADDR_IN_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;
}
if (write_method)
{
return (*write_method)(action, val, val_type, val_len,
- statP, suffix, suffix_len, v);
+ statP, suffix, suffix_len);
}
else
{
u_char *ptr;
size_t len;
long version;
- const char progname[] = QUAGGA_PROGNAME "-" QUAGGA_VERSION;
+ const char progname[] = FRR_SMUX_NAME "-" FRR_VERSION;
if (debug_smux)
{
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 (const oid *name, size_t namelen,
+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,
- unsigned int tick, u_char sptrap)
+ u_char sptrap)
{
unsigned int i;
u_char buf[BUFSIZ];
smux_sock = -1;
}
}
-\f
+
void
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
+
static int
smux_str2oid (const char *str, oid *oid, size_t *oid_len)
{
return 0;
}
-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;
-}
-
static int
smux_peer_default (void)
{
"SNMP MUX peer settings\n"
"Object ID used in SMUX peering\n")
{
- if (smux_peer_oid (vty, argv[0], NULL) == 0)
+ int idx_oid = 2;
+ if (smux_peer_oid (vty, argv[idx_oid]->arg, NULL) == 0)
{
smux_start();
return CMD_SUCCESS;
"SMUX peering object ID\n"
"SMUX peering password\n")
{
- if (smux_peer_oid (vty, argv[0], argv[1]) == 0)
+ int idx_oid = 2;
+ if (smux_peer_oid (vty, argv[idx_oid]->arg, argv[3]->rg) == 0)
{
smux_start();
return CMD_SUCCESS;
DEFUN (no_smux_peer,
no_smux_peer_cmd,
- "no smux peer",
+ "no smux peer [OID [PASSWORD]]",
NO_STR
"SNMP MUX protocol settings\n"
- "SNMP MUX peer settings\n")
+ "SNMP MUX peer settings\n"
+ "SMUX peering object ID\n"
+ "SMUX peering password\n")
{
smux_stop();
return smux_peer_default ();
}
-ALIAS (no_smux_peer,
- no_smux_peer_oid_cmd,
- "no smux peer OID",
- NO_STR
- "SNMP MUX protocol settings\n"
- "SNMP MUX peer settings\n"
- "SMUX peering object ID\n")
-
-ALIAS (no_smux_peer,
- no_smux_peer_oid_password_cmd,
- "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")
-
static int
config_write_smux (struct vty *vty)
{
void
smux_init (struct thread_master *tm)
{
+ assert (tm);
/* copy callers thread master */
- master = tm;
+ smux_master = tm;
/* Make MIB tree. */
treelist = list_new();
/* Schedule first connection. */
smux_event (SMUX_SCHEDULE, 0);
}
-#endif /* HAVE_SNMP */
+#endif /* SNMP_SMUX */