2 * Copyright (C) 1999 Kunihiro Ishiguro <kunihiro@zebra.org>
4 * This file is part of GNU Zebra.
6 * GNU Zebra is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2, or (at your option) any
11 * GNU Zebra is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with GNU Zebra; see the file COPYING. If not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
26 #include <net-snmp/net-snmp-config.h>
30 #include <snmp_impl.h>
39 #include "sockunion.h"
41 #define min(A,B) ((A) < (B) ? (A) : (B))
43 enum smux_event
{SMUX_SCHEDULE
, SMUX_CONNECT
, SMUX_READ
};
45 void smux_event (enum smux_event
, int);
51 /* SMUX subtree list. */
52 struct list
*treelist
;
58 /* SMUX default oid. */
59 oid
*smux_default_oid
;
60 size_t smux_default_oid_len
;
64 char *smux_default_passwd
= "";
66 /* SMUX read threads. */
67 struct thread
*smux_read_thread
;
69 /* SMUX connect thrads. */
70 struct thread
*smux_connect_thread
;
72 /* SMUX debug flag. */
75 /* SMUX failure count. */
79 struct cmd_node smux_node
=
82 "" /* SMUX has no interface. */
86 oid_copy (void *dest
, void *src
, size_t size
)
88 return memcpy (dest
, src
, size
* sizeof (oid
));
92 oid2in_addr (oid oid
[], int len
, struct in_addr
*addr
)
100 pnt
= (u_char
*) addr
;
102 for (i
= 0; i
< len
; i
++)
107 oid_copy_addr (oid oid
[], struct in_addr
*addr
, int len
)
115 pnt
= (u_char
*) addr
;
117 for (i
= 0; i
< len
; i
++)
122 oid_compare (oid
*o1
, int o1_len
, oid
*o2
, int o2_len
)
126 for (i
= 0; i
< min (o1_len
, o2_len
); i
++)
130 else if (o1
[i
] > o2
[i
])
142 oid_compare_part (oid
*o1
, int o1_len
, oid
*o2
, int o2_len
)
146 for (i
= 0; i
< min (o1_len
, o2_len
); i
++)
150 else if (o1
[i
] > o2
[i
])
160 smux_oid_dump (char *prefix
, oid
*oid
, size_t oid_len
)
164 char buf
[MAX_OID_LEN
* 3];
168 for (i
= 0; i
< oid_len
; i
++)
170 sprintf (buf
+ strlen (buf
), "%s%d", first
? "" : ".", (int) oid
[i
]);
173 zlog_info ("%s: %s", prefix
, buf
);
181 struct addrinfo hints
, *res0
, *res
;
184 struct sockaddr_in serv
;
190 memset(&hints
, 0, sizeof(hints
));
191 hints
.ai_family
= PF_UNSPEC
;
192 hints
.ai_socktype
= SOCK_STREAM
;
193 gai
= getaddrinfo(NULL
, "smux", &hints
, &res0
);
194 if (gai
== EAI_SERVICE
)
196 char servbuf
[NI_MAXSERV
];
197 sprintf(servbuf
,"%d",SMUX_PORT_DEFAULT
);
198 servbuf
[sizeof (servbuf
) - 1] = '\0';
199 gai
= getaddrinfo(NULL
, servbuf
, &hints
, &res0
);
203 zlog_warn("Cannot locate loopback service smux");
206 for(res
=res0
; res
; res
=res
->ai_next
)
208 if (res
->ai_family
!= AF_INET
210 && res
->ai_family
!= AF_INET6
211 #endif /* HAVE_IPV6 */
215 sock
= socket(res
->ai_family
, res
->ai_socktype
, res
->ai_protocol
);
218 sockopt_reuseaddr (sock
);
219 sockopt_reuseport (sock
);
220 ret
= connect (sock
, res
->ai_addr
, res
->ai_addrlen
);
231 zlog_warn ("Can't connect to SNMP agent with SMUX");
233 sock
= socket (AF_INET
, SOCK_STREAM
, 0);
236 zlog_warn ("Can't make socket for SNMP");
240 memset (&serv
, 0, sizeof (struct sockaddr_in
));
241 serv
.sin_family
= AF_INET
;
243 serv
.sin_len
= sizeof (struct sockaddr_in
);
244 #endif /* HAVE_SIN_LEN */
246 sp
= getservbyname ("smux", "tcp");
248 serv
.sin_port
= sp
->s_port
;
250 serv
.sin_port
= htons (SMUX_PORT_DEFAULT
);
252 serv
.sin_addr
.s_addr
= htonl (INADDR_LOOPBACK
);
254 sockopt_reuseaddr (sock
);
255 sockopt_reuseport (sock
);
257 ret
= connect (sock
, (struct sockaddr
*) &serv
, sizeof (struct sockaddr_in
));
262 zlog_warn ("Can't connect to SNMP agent with SMUX");
270 smux_getresp_send (oid objid
[], size_t objid_len
, long reqid
, long errstat
,
271 long errindex
, u_char val_type
, void *arg
, size_t arg_len
)
275 u_char
*ptr
, *h1
, *h1e
, *h2
, *h2e
;
284 zlog_info ("SMUX GETRSP send");
285 zlog_info ("SMUX GETRSP reqid: %ld", reqid
);
289 /* Place holder h1 for complete sequence */
290 ptr
= asn_build_sequence (ptr
, &len
, (u_char
) SMUX_GETRSP
, 0);
293 ptr
= asn_build_int (ptr
, &len
,
294 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
295 &reqid
, sizeof (reqid
));
298 zlog_info ("SMUX GETRSP errstat: %ld", errstat
);
300 ptr
= asn_build_int (ptr
, &len
,
301 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
302 &errstat
, sizeof (errstat
));
304 zlog_info ("SMUX GETRSP errindex: %ld", errindex
);
306 ptr
= asn_build_int (ptr
, &len
,
307 (u_char
) (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
308 &errindex
, sizeof (errindex
));
311 /* Place holder h2 for one variable */
312 ptr
= asn_build_sequence (ptr
, &len
,
313 (u_char
)(ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
317 ptr
= snmp_build_var_op (ptr
, objid
, &objid_len
,
318 val_type
, arg_len
, arg
, &len
);
320 /* Now variable size is known, fill in size */
321 asn_build_sequence(h2
,&length
,(u_char
)(ASN_SEQUENCE
|ASN_CONSTRUCTOR
),ptr
-h2e
);
323 /* Fill in size of whole sequence */
324 asn_build_sequence(h1
,&length
,(u_char
)SMUX_GETRSP
,ptr
-h1e
);
327 zlog_info ("SMUX getresp send: %d", ptr
- buf
);
329 ret
= send (smux_sock
, buf
, (ptr
- buf
), 0);
333 smux_var (char *ptr
, int len
, oid objid
[], size_t *objid_len
,
335 u_char
*var_val_type
,
344 zlog_info ("SMUX var parse: len %d", len
);
347 ptr
= asn_parse_header (ptr
, &len
, &type
);
351 zlog_info ("SMUX var parse: type %d len %d", type
, len
);
352 zlog_info ("SMUX var parse: type must be %d",
353 (ASN_SEQUENCE
| ASN_CONSTRUCTOR
));
356 /* Parse var option. */
357 *objid_len
= MAX_OID_LEN
;
358 ptr
= snmp_parse_var_op(ptr
, objid
, objid_len
, &val_type
,
359 &val_len
, &val
, &len
);
362 *var_val_len
= val_len
;
365 *var_value
= (void*) val
;
368 *var_val_type
= val_type
;
370 /* Requested object id length is objid_len. */
372 smux_oid_dump ("Request OID", objid
, *objid_len
);
375 zlog_info ("SMUX val_type: %d", val_type
);
377 /* Check request value type. */
382 /* In case of SMUX_GET or SMUX_GET_NEXT val_type is set to
384 zlog_info ("ASN_NULL");
388 zlog_info ("ASN_INTEGER");
394 zlog_info ("ASN_COUNTER");
397 zlog_info ("ASN_COUNTER64");
400 zlog_info ("ASN_IPADDRESS");
403 zlog_info ("ASN_OCTET_STR");
408 zlog_info ("ASN_OPAQUE");
410 case SNMP_NOSUCHOBJECT
:
411 zlog_info ("SNMP_NOSUCHOBJECT");
413 case SNMP_NOSUCHINSTANCE
:
414 zlog_info ("SNMP_NOSUCHINSTANCE");
416 case SNMP_ENDOFMIBVIEW
:
417 zlog_info ("SNMP_ENDOFMIBVIEW");
420 zlog_info ("ASN_BIT_STR");
423 zlog_info ("Unknown type");
429 /* NOTE: all 3 functions (smux_set, smux_get & smux_getnext) are based on
430 ucd-snmp smux and as such suppose, that the peer receives in the message
431 only one variable. Fortunately, IBM seems to do the same in AIX. */
434 smux_set (oid
*reqid
, size_t *reqid_len
,
435 u_char val_type
, void *val
, size_t val_len
, int action
)
438 struct subtree
*subtree
;
444 u_char
*statP
= NULL
;
445 WriteMethod
*write_method
= NULL
;
446 struct listnode
*node
;
449 for (node
= treelist
->head
; node
; node
= node
->next
)
451 subtree
= node
->data
;
452 subresult
= oid_compare_part (reqid
, *reqid_len
,
453 subtree
->name
, subtree
->name_len
);
455 /* Subtree matched. */
458 /* Prepare suffix. */
459 suffix
= reqid
+ subtree
->name_len
;
460 suffix_len
= *reqid_len
- subtree
->name_len
;
463 /* Check variables. */
464 for (j
= 0; j
< subtree
->variables_num
; j
++)
466 v
= &subtree
->variables
[j
];
468 /* Always check suffix */
469 result
= oid_compare_part (suffix
, suffix_len
,
470 v
->name
, v
->namelen
);
472 /* This is exact match so result must be zero. */
476 zlog_info ("SMUX function call index is %d", v
->magic
);
478 statP
= (*v
->findVar
) (v
, suffix
, &suffix_len
, 1,
479 &val_len
, &write_method
);
483 return (*write_method
)(action
, val
, val_type
, val_len
,
484 statP
, suffix
, suffix_len
, v
);
488 return SNMP_ERR_READONLY
;
492 /* If above execution is failed or oid is small (so
493 there is no further match). */
495 return SNMP_ERR_NOSUCHNAME
;
499 return SNMP_ERR_NOSUCHNAME
;
503 smux_get (oid
*reqid
, size_t *reqid_len
, int exact
,
504 u_char
*val_type
,void **val
, size_t *val_len
)
507 struct subtree
*subtree
;
513 WriteMethod
*write_method
=NULL
;
514 struct listnode
*node
;
517 for (node
= treelist
->head
; node
; node
= node
->next
)
519 subtree
= node
->data
;
520 subresult
= oid_compare_part (reqid
, *reqid_len
,
521 subtree
->name
, subtree
->name_len
);
523 /* Subtree matched. */
526 /* Prepare suffix. */
527 suffix
= reqid
+ subtree
->name_len
;
528 suffix_len
= *reqid_len
- subtree
->name_len
;
531 /* Check variables. */
532 for (j
= 0; j
< subtree
->variables_num
; j
++)
534 v
= &subtree
->variables
[j
];
536 /* Always check suffix */
537 result
= oid_compare_part (suffix
, suffix_len
,
538 v
->name
, v
->namelen
);
540 /* This is exact match so result must be zero. */
544 zlog_info ("SMUX function call index is %d", v
->magic
);
546 *val
= (*v
->findVar
) (v
, suffix
, &suffix_len
, exact
,
547 val_len
, &write_method
);
549 /* There is no instance. */
551 return SNMP_NOSUCHINSTANCE
;
553 /* Call is suceed. */
559 /* If above execution is failed or oid is small (so
560 there is no further match). */
562 return SNMP_ERR_NOSUCHNAME
;
566 return SNMP_ERR_NOSUCHNAME
;
570 smux_getnext (oid
*reqid
, size_t *reqid_len
, int exact
,
571 u_char
*val_type
,void **val
, size_t *val_len
)
574 oid save
[MAX_OID_LEN
];
576 struct subtree
*subtree
;
582 WriteMethod
*write_method
=NULL
;
583 struct listnode
*node
;
586 /* Save incoming request. */
587 oid_copy (save
, reqid
, *reqid_len
);
588 savelen
= *reqid_len
;
591 for (node
= treelist
->head
; node
; node
= node
->next
)
593 subtree
= node
->data
;
594 subresult
= oid_compare_part (reqid
, *reqid_len
,
595 subtree
->name
, subtree
->name_len
);
597 /* If request is in the tree. The agent has to make sure we
598 only receive requests we have registered for. */
599 /* Unfortunately, that's not true. In fact, a SMUX subagent has to
600 behave as if it manages the whole SNMP MIB tree itself. It's the
601 duty of the master agent to collect the best answer and return it
602 to the manager. See RFC 1227 chapter 3.1.6 for the glory details
603 :-). ucd-snmp really behaves bad here as it actually might ask
604 multiple times for the same GETNEXT request as it throws away the
605 answer when it expects it in a different subtree and might come
606 back later with the very same request. --jochen */
610 /* Prepare suffix. */
611 suffix
= reqid
+ subtree
->name_len
;
612 suffix_len
= *reqid_len
- subtree
->name_len
;
615 oid_copy(reqid
, subtree
->name
, subtree
->name_len
);
616 *reqid_len
= subtree
->name_len
;
618 for (j
= 0; j
< subtree
->variables_num
; j
++)
621 v
= &subtree
->variables
[j
];
623 /* Next then check result >= 0. */
625 result
= oid_compare_part (suffix
, suffix_len
,
626 v
->name
, v
->namelen
);
631 zlog_info ("SMUX function call index is %d", v
->magic
);
634 oid_copy(suffix
, v
->name
, v
->namelen
);
635 suffix_len
= v
->namelen
;
637 *val
= (*v
->findVar
) (v
, suffix
, &suffix_len
, exact
,
638 val_len
, &write_method
);
639 *reqid_len
= suffix_len
+ subtree
->name_len
;
649 memcpy (reqid
, save
, savelen
* sizeof(oid
));
650 *reqid_len
= savelen
;
652 return SNMP_ERR_NOSUCHNAME
;
655 /* GET message header. */
657 smux_parse_get_header (char *ptr
, size_t *len
, long *reqid
)
664 ptr
= asn_parse_int (ptr
, len
, &type
, reqid
, sizeof (*reqid
));
667 zlog_info ("SMUX GET reqid: %d len: %d", (int) *reqid
, (int) *len
);
670 ptr
= asn_parse_int (ptr
, len
, &type
, &errstat
, sizeof (errstat
));
673 zlog_info ("SMUX GET errstat %ld len: %d", errstat
, *len
);
676 ptr
= asn_parse_int (ptr
, len
, &type
, &errindex
, sizeof (errindex
));
679 zlog_info ("SMUX GET errindex %ld len: %d", errindex
, *len
);
685 smux_parse_set (char *ptr
, size_t len
, int action
)
688 oid oid
[MAX_OID_LEN
];
696 zlog_info ("SMUX SET(%s) message parse: len %d",
697 (RESERVE1
== action
) ? "RESERVE1" : ((FREE
== action
) ? "FREE" : "COMMIT"),
700 /* Parse SET message header. */
701 ptr
= smux_parse_get_header (ptr
, &len
, &reqid
);
703 /* Parse SET message object ID. */
704 ptr
= smux_var (ptr
, len
, oid
, &oid_len
, &val_len
, &val_type
, &val
);
706 ret
= smux_set (oid
, &oid_len
, val_type
, val
, val_len
, action
);
708 zlog_info ("SMUX SET ret %d", ret
);
711 if (RESERVE1
== action
)
712 smux_getresp_send (oid
, oid_len
, reqid
, ret
, 3, ASN_NULL
, NULL
, 0);
716 smux_parse_get (char *ptr
, size_t len
, int exact
)
719 oid oid
[MAX_OID_LEN
];
727 zlog_info ("SMUX GET message parse: len %d", len
);
729 /* Parse GET message header. */
730 ptr
= smux_parse_get_header (ptr
, &len
, &reqid
);
732 /* Parse GET message object ID. We needn't the value come */
733 ptr
= smux_var (ptr
, len
, oid
, &oid_len
, NULL
, NULL
, NULL
);
735 /* Traditional getstatptr. */
737 ret
= smux_get (oid
, &oid_len
, exact
, &val_type
, &val
, &val_len
);
739 ret
= smux_getnext (oid
, &oid_len
, exact
, &val_type
, &val
, &val_len
);
743 smux_getresp_send (oid
, oid_len
, reqid
, 0, 0, val_type
, val
, val_len
);
745 smux_getresp_send (oid
, oid_len
, reqid
, ret
, 3, ASN_NULL
, NULL
, 0);
748 /* Parse SMUX_CLOSE message. */
750 smux_parse_close (char *ptr
, int len
)
756 reason
= (reason
<< 8) | (long) *ptr
;
759 zlog_info ("SMUX_CLOSE with reason: %ld", reason
);
762 /* SMUX_RRSP message. */
764 smux_parse_rrsp (char *ptr
, int len
)
769 ptr
= asn_parse_int (ptr
, &len
, &val
, &errstat
, sizeof (errstat
));
772 zlog_info ("SMUX_RRSP value: %d errstat: %ld", val
, errstat
);
775 /* Parse SMUX message. */
777 smux_parse (char *ptr
, int len
)
779 /* This buffer we'll use for SOUT message. We could allocate it with
780 malloc and save only static pointer/lenght, but IMHO static
781 buffer is a faster solusion. */
782 static u_char sout_save_buff
[SMUXMAXPKTSIZE
];
783 static int sout_save_len
= 0;
785 int len_income
= len
; /* see note below: YYY */
789 rollback
= ptr
[2]; /* important only for SMUX_SOUT */
791 process_rest
: /* see note below: YYY */
793 /* Parse SMUX message type and subsequent length. */
794 ptr
= asn_parse_header (ptr
, &len
, &type
);
797 zlog_info ("SMUX message received type: %d rest len: %d", type
, len
);
802 /* Open must be not send from SNMP agent. */
803 zlog_warn ("SMUX_OPEN received: resetting connection.");
807 /* SMUX_RREQ message is invalid for us. */
808 zlog_warn ("SMUX_RREQ received: resetting connection.");
812 /* SMUX_SOUT message is now valied for us. */
814 zlog_info ("SMUX_SOUT(%s)", rollback
? "rollback" : "commit");
816 if (sout_save_len
> 0)
818 smux_parse_set (sout_save_buff
, sout_save_len
, rollback
? FREE
: COMMIT
);
822 zlog_warn ("SMUX_SOUT sout_save_len=%d - invalid", (int) sout_save_len
);
826 /* YYY: this strange code has to solve the "slow peer"
827 problem: When agent sends SMUX_SOUT message it doesn't
828 wait any responce and may send some next message to
829 subagent. Then the peer in 'smux_read()' will recieve
830 from socket the 'concatenated' buffer, contaning both
831 SMUX_SOUT message and the next one
832 (SMUX_GET/SMUX_GETNEXT/SMUX_GET). So we should check: if
833 the buffer is longer than 3 ( length of SMUX_SOUT ), we
834 must process the rest of it. This effect may be observed
835 if 'debug_smux' is set to '1' */
837 len
= len_income
- 3;
842 /* SMUX_GETRSP message is invalid for us. */
843 zlog_warn ("SMUX_GETRSP received: resetting connection.");
847 /* Close SMUX connection. */
849 zlog_info ("SMUX_CLOSE");
850 smux_parse_close (ptr
, len
);
854 /* This is response for register message. */
856 zlog_info ("SMUX_RRSP");
857 smux_parse_rrsp (ptr
, len
);
860 /* Exact request for object id. */
862 zlog_info ("SMUX_GET");
863 smux_parse_get (ptr
, len
, 1);
866 /* Next request for object id. */
868 zlog_info ("SMUX_GETNEXT");
869 smux_parse_get (ptr
, len
, 0);
872 /* SMUX_SET is supported with some limitations. */
874 zlog_info ("SMUX_SET");
876 /* save the data for future SMUX_SOUT */
877 memcpy (sout_save_buff
, ptr
, len
);
879 smux_parse_set (ptr
, len
, RESERVE1
);
882 zlog_info ("Unknown type: %d", type
);
888 /* SMUX message read function. */
890 smux_read (struct thread
*t
)
894 u_char buf
[SMUXMAXPKTSIZE
];
898 sock
= THREAD_FD (t
);
899 smux_read_thread
= NULL
;
902 zlog_info ("SMUX read start");
904 /* Read message from SMUX socket. */
905 len
= recv (sock
, buf
, SMUXMAXPKTSIZE
, 0);
909 zlog_warn ("Can't read all SMUX packet: %s", strerror (errno
));
912 smux_event (SMUX_CONNECT
, 0);
918 zlog_warn ("SMUX connection closed: %d", sock
);
921 smux_event (SMUX_CONNECT
, 0);
926 zlog_info ("SMUX read len: %d", len
);
928 /* Parse the message. */
929 ret
= smux_parse (buf
, len
);
935 smux_event (SMUX_CONNECT
, 0);
939 /* Regiser read thread. */
940 smux_event (SMUX_READ
, sock
);
952 u_char progname
[] = "zebra-" ZEBRA_VERSION
;
956 smux_oid_dump ("SMUX open oid", smux_oid
, smux_oid_len
);
957 zlog_info ("SMUX open progname: %s", progname
);
958 zlog_info ("SMUX open password: %s", smux_passwd
);
964 /* SMUX Header. As placeholder. */
965 ptr
= asn_build_header (ptr
, &len
, (u_char
) SMUX_OPEN
, 0);
969 ptr
= asn_build_int (ptr
, &len
,
970 (u_char
)(ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
971 &version
, sizeof (u_long
));
973 /* SMUX connection oid. */
974 ptr
= asn_build_objid (ptr
, &len
,
976 (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_OBJECT_ID
),
977 smux_oid
, smux_oid_len
);
979 /* SMUX connection description. */
980 ptr
= asn_build_string (ptr
, &len
,
982 (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_OCTET_STR
),
983 progname
, strlen (progname
));
985 /* SMUX connection password. */
986 ptr
= asn_build_string (ptr
, &len
,
988 (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_OCTET_STR
),
989 smux_passwd
, strlen (smux_passwd
));
991 /* Fill in real SMUX header. We exclude ASN header size (2). */
993 asn_build_header (buf
, &len
, (u_char
) SMUX_OPEN
, (ptr
- buf
) - 2);
995 return send (sock
, buf
, (ptr
- buf
), 0);
999 smux_trap (oid
*name
, size_t namelen
,
1000 oid
*iname
, size_t inamelen
,
1001 struct trap_object
*trapobj
, size_t trapobjlen
,
1002 unsigned int tick
, u_char sptrap
)
1008 struct in_addr addr
;
1016 /* When SMUX connection is not established. */
1021 ptr
= asn_build_header (ptr
, &len
, (u_char
) SMUX_TRAP
, 0);
1023 /* Sub agent enterprise oid. */
1024 ptr
= asn_build_objid (ptr
, &len
,
1026 (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_OBJECT_ID
),
1027 smux_oid
, smux_oid_len
);
1031 ptr
= asn_build_string (ptr
, &len
,
1033 (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_IPADDRESS
),
1034 (u_char
*)&addr
, sizeof (struct in_addr
));
1036 /* Generic trap integer. */
1037 val
= SNMP_TRAP_ENTERPRISESPECIFIC
;
1038 ptr
= asn_build_int (ptr
, &len
,
1039 (u_char
)(ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
1040 &val
, sizeof (int));
1042 /* Specific trap integer. */
1044 ptr
= asn_build_int (ptr
, &len
,
1045 (u_char
)(ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
1046 &val
, sizeof (int));
1048 /* Timeticks timestamp. */
1050 ptr
= asn_build_unsigned_int (ptr
, &len
,
1051 (u_char
)(ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_TIMETICKS
),
1052 &val
, sizeof (int));
1056 ptr
= asn_build_sequence (ptr
, &len
,
1057 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
1061 /* Iteration for each objects. */
1063 for (i
= 0; i
< trapobjlen
; i
++)
1066 oid oid
[MAX_OID_LEN
];
1073 oid_copy (oid
, name
, namelen
);
1074 oid_copy (oid
+ namelen
, trapobj
[i
].name
, trapobj
[i
].namelen
);
1075 oid_copy (oid
+ namelen
+ trapobj
[i
].namelen
, iname
, inamelen
);
1076 oid_len
= namelen
+ trapobj
[i
].namelen
+ inamelen
;
1079 smux_oid_dump ("Trap", oid
, oid_len
);
1081 ret
= smux_get (oid
, &oid_len
, 1, &val_type
, &val
, &val_len
);
1084 zlog_info ("smux_get result %d", ret
);
1087 ptr
= snmp_build_var_op (ptr
, oid
, &oid_len
,
1088 val_type
, val_len
, val
, &len
);
1091 /* Now variable size is known, fill in size */
1092 asn_build_sequence(h1
, &length
,
1093 (u_char
) (ASN_SEQUENCE
| ASN_CONSTRUCTOR
),
1096 /* Fill in size of whole sequence */
1098 asn_build_header (buf
, &len
, (u_char
) SMUX_TRAP
, (ptr
- buf
) - 2);
1100 return send (smux_sock
, buf
, (ptr
- buf
), 0);
1104 smux_register (int sock
)
1111 struct subtree
*subtree
;
1112 struct listnode
*node
;
1116 for (node
= treelist
->head
; node
; node
= node
->next
)
1121 subtree
= node
->data
;
1123 /* SMUX RReq Header. */
1124 ptr
= asn_build_header (ptr
, &len
, (u_char
) SMUX_RREQ
, 0);
1126 /* Register MIB tree. */
1127 ptr
= asn_build_objid (ptr
, &len
,
1129 (ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_OBJECT_ID
),
1130 subtree
->name
, subtree
->name_len
);
1134 ptr
= asn_build_int (ptr
, &len
,
1135 (u_char
)(ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
1136 &priority
, sizeof (u_long
));
1139 operation
= 2; /* Register R/W */
1140 ptr
= asn_build_int (ptr
, &len
,
1141 (u_char
)(ASN_UNIVERSAL
| ASN_PRIMITIVE
| ASN_INTEGER
),
1142 &operation
, sizeof (u_long
));
1146 smux_oid_dump ("SMUX register oid", subtree
->name
, subtree
->name_len
);
1147 zlog_info ("SMUX register priority: %ld", priority
);
1148 zlog_info ("SMUX register operation: %ld", operation
);
1152 asn_build_header (buf
, &len
, (u_char
) SMUX_RREQ
, (ptr
- buf
) - 2);
1153 ret
= send (sock
, buf
, (ptr
- buf
), 0);
1160 /* Try to connect to SNMP agent. */
1162 smux_connect (struct thread
*t
)
1167 zlog_info ("SMUX connect try %d", fail
+ 1);
1169 /* Clear thread poner of myself. */
1170 smux_connect_thread
= NULL
;
1172 /* Make socket. Try to connect. */
1173 smux_sock
= smux_socket ();
1176 if (++fail
< SMUX_MAX_FAILURE
)
1177 smux_event (SMUX_CONNECT
, 0);
1181 /* Send OPEN PDU. */
1182 ret
= smux_open (smux_sock
);
1185 zlog_warn ("SMUX open message send failed: %s", strerror (errno
));
1188 if (++fail
< SMUX_MAX_FAILURE
)
1189 smux_event (SMUX_CONNECT
, 0);
1193 /* Send any outstanding register PDUs. */
1194 ret
= smux_register (smux_sock
);
1197 zlog_warn ("SMUX register message send failed: %s", strerror (errno
));
1200 if (++fail
< SMUX_MAX_FAILURE
)
1201 smux_event (SMUX_CONNECT
, 0);
1205 /* Everything goes fine. */
1206 smux_event (SMUX_READ
, smux_sock
);
1211 /* Clear all SMUX related resources. */
1215 if (smux_read_thread
)
1216 thread_cancel (smux_read_thread
);
1217 if (smux_connect_thread
)
1218 thread_cancel (smux_connect_thread
);
1227 extern struct thread_master
*master
;
1230 smux_event (enum smux_event event
, int sock
)
1235 smux_connect_thread
= thread_add_event (master
, smux_connect
, NULL
, 0);
1238 smux_connect_thread
= thread_add_timer (master
, smux_connect
, NULL
, 10);
1241 smux_read_thread
= thread_add_read (master
, smux_read
, NULL
, sock
);
1249 smux_str2oid (char *str
, oid
*oid
, size_t *oid_len
)
1265 if (! isdigit (*str
))
1268 while (isdigit (*str
))
1271 val
+= (*str
- '0');
1292 smux_oid_dup (oid
*objid
, size_t objid_len
)
1296 new = XMALLOC (MTYPE_TMP
, sizeof (oid
) * objid_len
);
1297 oid_copy (new, objid
, objid_len
);
1303 smux_peer_oid (struct vty
*vty
, char *oid_str
, char *passwd_str
)
1306 oid oid
[MAX_OID_LEN
];
1309 ret
= smux_str2oid (oid_str
, oid
, &oid_len
);
1312 vty_out (vty
, "object ID malformed%s", VTY_NEWLINE
);
1316 if (smux_oid
&& smux_oid
!= smux_default_oid
)
1319 if (smux_passwd
&& smux_passwd
!= smux_default_passwd
)
1325 smux_oid
= smux_oid_dup (oid
, oid_len
);
1326 smux_oid_len
= oid_len
;
1329 smux_passwd
= strdup (passwd_str
);
1335 smux_header_generic (struct variable
*v
, oid
*name
, size_t *length
, int exact
,
1336 size_t *var_len
, WriteMethod
**write_method
)
1338 oid fulloid
[MAX_OID_LEN
];
1341 oid_copy (fulloid
, v
->name
, v
->namelen
);
1342 fulloid
[v
->namelen
] = 0;
1343 /* Check against full instance. */
1344 ret
= oid_compare (name
, *length
, fulloid
, v
->namelen
+ 1);
1346 /* Check single instance. */
1347 if ((exact
&& (ret
!= 0)) || (!exact
&& (ret
>= 0)))
1348 return MATCH_FAILED
;
1350 /* In case of getnext, fill in full instance. */
1351 memcpy (name
, fulloid
, (v
->namelen
+ 1) * sizeof (oid
));
1352 *length
= v
->namelen
+ 1;
1355 *var_len
= sizeof(long); /* default to 'long' results */
1357 return MATCH_SUCCEEDED
;
1361 smux_peer_default ()
1363 if (smux_oid
!= smux_default_oid
)
1366 smux_oid
= smux_default_oid
;
1367 smux_oid_len
= smux_default_oid_len
;
1369 if (smux_passwd
!= smux_default_passwd
)
1372 smux_passwd
= smux_default_passwd
;
1380 "SNMP MUX protocol settings\n"
1381 "SNMP MUX peer settings\n"
1382 "Object ID used in SMUX peering\n")
1384 return smux_peer_oid (vty
, argv
[0], NULL
);
1387 DEFUN (smux_peer_password
,
1388 smux_peer_password_cmd
,
1389 "smux peer OID PASSWORD",
1390 "SNMP MUX protocol settings\n"
1391 "SNMP MUX peer settings\n"
1392 "SMUX peering object ID\n"
1393 "SMUX peering password\n")
1395 return smux_peer_oid (vty
, argv
[0], argv
[1]);
1398 DEFUN (no_smux_peer
,
1402 "SNMP MUX protocol settings\n"
1403 "SNMP MUX peer settings\n"
1404 "Object ID used in SMUX peering\n")
1406 return smux_peer_default ();
1409 DEFUN (no_smux_peer_password
,
1410 no_smux_peer_password_cmd
,
1411 "no smux peer OID PASSWORD",
1413 "SNMP MUX protocol settings\n"
1414 "SNMP MUX peer settings\n"
1415 "SMUX peering object ID\n"
1416 "SMUX peering password\n")
1418 return smux_peer_default ();
1422 config_write_smux (struct vty
*vty
)
1427 if (smux_oid
!= smux_default_oid
|| smux_passwd
!= smux_default_passwd
)
1429 vty_out (vty
, "smux peer ");
1430 for (i
= 0; i
< smux_oid_len
; i
++)
1432 vty_out (vty
, "%s%d", first
? "" : ".", (int) smux_oid
[i
]);
1435 vty_out (vty
, " %s%s", smux_passwd
, VTY_NEWLINE
);
1440 /* Register subtree to smux master tree. */
1442 smux_register_mib (char *descr
, struct variable
*var
, size_t width
, int num
,
1443 oid name
[], size_t namelen
)
1445 struct subtree
*tree
;
1447 tree
= (struct subtree
*)malloc(sizeof(struct subtree
));
1448 oid_copy (tree
->name
, name
, namelen
);
1449 tree
->name_len
= namelen
;
1450 tree
->variables
= var
;
1451 tree
->variables_num
= num
;
1452 tree
->variables_width
= width
;
1453 tree
->registered
= 0;
1454 listnode_add_sort(treelist
, tree
);
1460 /* Setting configuration to default. */
1461 smux_peer_default ();
1464 /* Compare function to keep treelist sorted */
1466 smux_tree_cmp(struct subtree
*tree1
, struct subtree
*tree2
)
1468 return oid_compare(tree1
->name
, tree1
->name_len
,
1469 tree2
->name
, tree2
->name_len
);
1472 /* Initialize some values then schedule first SMUX connection. */
1474 smux_init (oid defoid
[], size_t defoid_len
)
1476 /* Set default SMUX oid. */
1477 smux_default_oid
= defoid
;
1478 smux_default_oid_len
= defoid_len
;
1480 smux_oid
= smux_default_oid
;
1481 smux_oid_len
= smux_default_oid_len
;
1482 smux_passwd
= smux_default_passwd
;
1484 /* Make MIB tree. */
1485 treelist
= list_new();
1486 treelist
->cmp
= (int (*)(void *, void *))smux_tree_cmp
;
1488 /* Install commands. */
1489 install_node (&smux_node
, config_write_smux
);
1491 install_element (CONFIG_NODE
, &smux_peer_cmd
);
1492 install_element (CONFIG_NODE
, &smux_peer_password_cmd
);
1493 install_element (CONFIG_NODE
, &no_smux_peer_cmd
);
1494 install_element (CONFIG_NODE
, &no_smux_peer_password_cmd
);
1500 /* Schedule first connection. */
1501 smux_event (SMUX_SCHEDULE
, 0);
1503 #endif /* HAVE_SNMP */