diff options
author | Pat Ruddy <pat@voltanet.io> | 2020-09-28 17:35:35 +0200 |
---|---|---|
committer | Pat Ruddy <pat@voltanet.io> | 2021-02-02 10:37:06 +0100 |
commit | 0d020cd6d98f454f22723f404da99fa48b7b2751 (patch) | |
tree | fe2605ddf46460c25b38c03276b21b93dc049f25 | |
parent | bgpd: add MPLSVPN SNMP boilerplate (diff) | |
download | frr-0d020cd6d98f454f22723f404da99fa48b7b2751.tar.xz frr-0d020cd6d98f454f22723f404da99fa48b7b2751.zip |
bgpd, lib: add mplsL3VpnVrf table
Add SNMP support for L3vpn Vrf table as defined in [RFC4382]
Keep track of vrf status for the table and for future traps.
Signed-off-by: Pat Ruddy <pat@voltanet.io>
-rw-r--r-- | bgpd/bgp_mplsvpn_snmp.c | 328 | ||||
-rw-r--r-- | bgpd/bgp_nb_config.c | 3 | ||||
-rw-r--r-- | bgpd/bgp_vty.c | 2 | ||||
-rw-r--r-- | bgpd/bgp_zebra.c | 13 | ||||
-rw-r--r-- | bgpd/bgpd.c | 1 | ||||
-rw-r--r-- | bgpd/bgpd.h | 53 | ||||
-rw-r--r-- | lib/smux.h | 2 | ||||
-rw-r--r-- | lib/snmp.c | 28 |
8 files changed, 407 insertions, 23 deletions
diff --git a/bgpd/bgp_mplsvpn_snmp.c b/bgpd/bgp_mplsvpn_snmp.c index 0a8d39cb9..65fbf5413 100644 --- a/bgpd/bgp_mplsvpn_snmp.c +++ b/bgpd/bgp_mplsvpn_snmp.c @@ -41,8 +41,6 @@ #define BGP_mplsvpn_notif_enable_true 1 #define BGP_mplsvpn_notif_enable_false 2 -static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE; - /* MPLSL3VPN MIB described in RFC4382 */ #define MPLSL3VPNMIB 1, 3, 6, 1, 2, 1, 10, 166, 11 @@ -55,6 +53,22 @@ static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE; #define MPLSL3VPNVRFCONFRTEMXTHRSHTIME 6 #define MPLSL3VPNILLLBLRCVTHRSH 7 +/* MPLSL3VPN VRF Table */ +#define MPLSL3VPNVRFVPNID 1 +#define MPLSL3VPNVRFDESC 2 +#define MPLSL3VPNVRFRD 3 +#define MPLSL3VPNVRFCREATIONTIME 4 +#define MPLSL3VPNVRFOPERSTATUS 5 +#define MPLSL3VPNVRFACTIVEINTERFACES 6 +#define MPLSL3VPNVRFASSOCIATEDINTERFACES 7 +#define MPLSL3VPNVRFCONFMIDRTETHRESH 8 +#define MPLSL3VPNVRFCONFHIGHRTETHRSH 9 +#define MPLSL3VPNVRFCONFMAXROUTES 10 +#define MPLSL3VPNVRFCONFLASTCHANGED 11 +#define MPLSL3VPNVRFCONFROWSTATUS 12 +#define MPLSL3VPNVRFCONFADMINSTATUS 13 +#define MPLSL3VPNVRFCONFSTORAGETYPE 14 + /* SNMP value hack. */ #define INTEGER ASN_INTEGER #define INTEGER32 ASN_INTEGER @@ -62,12 +76,15 @@ static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE; #define OCTET_STRING ASN_OCTET_STR #define IPADDRESS ASN_IPADDRESS #define GAUGE32 ASN_UNSIGNED +#define TIMETICKS ASN_TIMETICKS /* Declare static local variables for convenience. */ SNMP_LOCAL_VARIABLES /* BGP-MPLS-MIB innstances */ static oid mpls_l3vpn_oid[] = {MPLSL3VPNMIB}; +static char rd_buf[RD_ADDRSTRLEN]; +static uint8_t bgp_mplsvpn_notif_enable = SNMP_FALSE; static uint8_t *mplsL3vpnConfiguredVrfs(struct variable *, oid[], size_t *, int, size_t *, WriteMethod **); @@ -91,6 +108,10 @@ static uint8_t *mplsL3vpnVrfConfRteMxThrshTime(struct variable *, oid[], static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable *, oid[], size_t *, int, size_t *, WriteMethod **); +static uint8_t *mplsL3vpnVrfTable(struct variable *, oid[], size_t *, int, + size_t *, WriteMethod **); + + static struct variable mpls_l3vpn_variables[] = { /* BGP version. */ {MPLSL3VPNCONFIGUREDVRFS, @@ -136,8 +157,168 @@ static struct variable mpls_l3vpn_variables[] = { 3, {1, 1, 7} }, + /* Vrf Table */ + {MPLSL3VPNVRFVPNID, + OCTET_STRING, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 2} }, + {MPLSL3VPNVRFDESC, + OCTET_STRING, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 3} }, + {MPLSL3VPNVRFRD, + OCTET_STRING, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 4} }, + {MPLSL3VPNVRFCREATIONTIME, + TIMETICKS, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 5} }, + {MPLSL3VPNVRFOPERSTATUS, + INTEGER, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 6} }, + {MPLSL3VPNVRFACTIVEINTERFACES, + GAUGE32, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 7} }, + {MPLSL3VPNVRFASSOCIATEDINTERFACES, + GAUGE32, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 8} }, + {MPLSL3VPNVRFCONFMIDRTETHRESH, + GAUGE32, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 9} }, + {MPLSL3VPNVRFCONFHIGHRTETHRSH, + GAUGE32, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 10} }, + {MPLSL3VPNVRFCONFMAXROUTES, + GAUGE32, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 11} }, + {MPLSL3VPNVRFCONFLASTCHANGED, + TIMETICKS, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 12} }, + {MPLSL3VPNVRFCONFROWSTATUS, + INTEGER, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 13} }, + {MPLSL3VPNVRFCONFADMINSTATUS, + INTEGER, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 14} }, + {MPLSL3VPNVRFCONFSTORAGETYPE, + INTEGER, + RONLY, + mplsL3vpnVrfTable, + 5, + {1, 2, 2, 1, 15} }, }; +/* timeticks are in hundredths of a second */ +static void bgp_mpls_l3vpn_update_timeticks(time_t *counter) +{ + struct timeval tv; + + monotime(&tv); + *counter = (tv.tv_sec * 100) + (tv.tv_usec / 10000); +} + +static int bgp_mpls_l3vpn_update_last_changed(struct bgp *bgp) +{ + if (bgp->snmp_stats) + bgp_mpls_l3vpn_update_timeticks( + &(bgp->snmp_stats->modify_time)); + return 0; +} + +static int bgp_init_snmp_stats(struct bgp *bgp) +{ + if (is_bgp_vrf_mplsvpn(bgp)) { + if (bgp->snmp_stats == NULL) { + bgp->snmp_stats = XCALLOC( + MTYPE_BGP, sizeof(struct bgp_snmp_stats)); + /* fix up added routes */ + if (bgp->snmp_stats) + bgp_mpls_l3vpn_update_timeticks( + &(bgp->snmp_stats->creation_time)); + } + } else { + if (bgp->snmp_stats) { + XFREE(MTYPE_BGP, bgp->snmp_stats); + bgp->snmp_stats = NULL; + } + } + /* Something changed - update the timestamp */ + bgp_mpls_l3vpn_update_last_changed(bgp); + return 0; +} + +static bool is_bgp_vrf_active(struct bgp *bgp) +{ + struct vrf *vrf; + struct interface *ifp; + + /* if there is one interface in the vrf which is up then it is deemed + * active + */ + vrf = vrf_lookup_by_id(bgp->vrf_id); + if (vrf == NULL) + return false; + RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) { + /* if we are in a vrf skip the l3mdev */ + if (bgp->name && strncmp(ifp->name, bgp->name, VRF_NAMSIZ) == 0) + continue; + + if (if_is_up(ifp)) + return true; + } + return false; +} + +static int bgp_vrf_check_update_active(struct bgp *bgp, struct interface *ifp) +{ + bool new_active = false; + + if (!is_bgp_vrf_mplsvpn(bgp) || bgp->snmp_stats == NULL) + return 0; + new_active = is_bgp_vrf_active(bgp); + if (bgp->snmp_stats->active != new_active) { + /* add trap in here */ + bgp->snmp_stats->active = new_active; + } + return 0; +} + static uint8_t *mplsL3vpnConfiguredVrfs(struct variable *v, oid name[], size_t *length, int exact, size_t *var_len, @@ -211,7 +392,6 @@ static int write_mplsL3vpnNotificationEnable(int action, uint8_t *var_val, { uint32_t intval; - zlog_debug("PJDR: %s", __func__); if (var_val_type != ASN_INTEGER) { return SNMP_ERR_WRONGTYPE; } @@ -234,7 +414,6 @@ static uint8_t *mplsL3vpnNotificationEnable(struct variable *v, oid name[], == MATCH_FAILED) return NULL; - zlog_debug("PJDR: %s", __func__); *write_method = write_mplsL3vpnNotificationEnable; return SNMP_INTEGER(bgp_mplsvpn_notif_enable); } @@ -276,8 +455,149 @@ static uint8_t *mplsL3vpnIllLblRcvThrsh(struct variable *v, oid name[], } +/* 1.3.6.1.2.1.10.166.11.1.2.2.1.x = 14*/ +#define VRFTAB_NAMELEN 14 + +static struct bgp *bgp_lookup_by_name_next(const char *vrf_name) +{ + struct bgp *bgp, *bgp_next = NULL; + struct listnode *node, *nnode; + bool first = false; + + /* + * the vrfs are not stored alphabetically but since we are using the + * vrf name as an index we need the getnext function to return them + * in a atrict order. Thus run through and find the best next one. + */ + for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) { + if (!is_bgp_vrf_mplsvpn(bgp)) + continue; + if (strnlen(vrf_name, VRF_NAMSIZ) == 0 && bgp_next == NULL) { + first = true; + bgp_next = bgp; + continue; + } + if (first || strncmp(bgp->name, vrf_name, VRF_NAMSIZ) > 0) { + if (bgp_next == NULL) + bgp_next = bgp; + else if (strncmp(bgp->name, bgp_next->name, VRF_NAMSIZ) + < 0) + bgp_next = bgp; + } + } + return bgp_next; +} + +static struct bgp *bgpL3vpnTable_lookup(struct variable *v, oid name[], + size_t *length, char *vrf_name, + int exact) +{ + struct bgp *bgp = NULL; + size_t namelen = v ? v->namelen : VRFTAB_NAMELEN; + int len; + + if (*length - namelen > VRF_NAMSIZ) + return NULL; + oid2string(name + namelen, *length - namelen, vrf_name); + if (exact) { + /* Check the length. */ + bgp = bgp_lookup_by_name(vrf_name); + if (bgp && !is_bgp_vrf_mplsvpn(bgp)) + return NULL; + } else { + bgp = bgp_lookup_by_name_next(vrf_name); + + if (bgp == NULL) + return NULL; + + len = strnlen(bgp->name, VRF_NAMSIZ); + oid_copy_str(name + namelen, bgp->name, len); + *length = len + namelen; + } + return bgp; +} + +static uint8_t *mplsL3vpnVrfTable(struct variable *v, oid name[], + size_t *length, int exact, size_t *var_len, + WriteMethod **write_method) +{ + char vrf_name[VRF_NAMSIZ]; + struct bgp *l3vpn_bgp; + + if (smux_header_table(v, name, length, exact, var_len, write_method) + == MATCH_FAILED) + return NULL; + + memset(vrf_name, 0, VRF_NAMSIZ); + l3vpn_bgp = bgpL3vpnTable_lookup(v, name, length, vrf_name, exact); + + if (!l3vpn_bgp) + return NULL; + + switch (v->magic) { + case MPLSL3VPNVRFVPNID: + *var_len = 0; + return NULL; + case MPLSL3VPNVRFDESC: + *var_len = strnlen(l3vpn_bgp->name, VRF_NAMSIZ); + return (uint8_t *)l3vpn_bgp->name; + case MPLSL3VPNVRFRD: + /* + * this is a horror show but the MIB dicates one RD per vrf + * and not one RD per AFI as we (FRR) have. So this little gem + * returns the V4 one if it's set OR the v6 one if it's set or + * zero-length string id neither are set + */ + memset(rd_buf, 0, RD_ADDRSTRLEN); + if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP].flags, + BGP_VPN_POLICY_TOVPN_RD_SET)) + prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP].tovpn_rd, + rd_buf, sizeof(rd_buf)); + else if (CHECK_FLAG(l3vpn_bgp->vpn_policy[AFI_IP6].flags, + BGP_VPN_POLICY_TOVPN_RD_SET)) + prefix_rd2str(&l3vpn_bgp->vpn_policy[AFI_IP6].tovpn_rd, + rd_buf, sizeof(rd_buf)); + + *var_len = strnlen(rd_buf, RD_ADDRSTRLEN); + return (uint8_t *)rd_buf; + case MPLSL3VPNVRFCREATIONTIME: + return SNMP_INTEGER( + (uint32_t)l3vpn_bgp->snmp_stats->creation_time); + case MPLSL3VPNVRFOPERSTATUS: + if (l3vpn_bgp->snmp_stats->active) + return SNMP_INTEGER(1); + else + return SNMP_INTEGER(2); + case MPLSL3VPNVRFACTIVEINTERFACES: + return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp, true)); + case MPLSL3VPNVRFASSOCIATEDINTERFACES: + return SNMP_INTEGER(bgp_vrf_interfaces(l3vpn_bgp, false)); + case MPLSL3VPNVRFCONFMIDRTETHRESH: + return SNMP_INTEGER(0); + case MPLSL3VPNVRFCONFHIGHRTETHRSH: + return SNMP_INTEGER(0); + case MPLSL3VPNVRFCONFMAXROUTES: + return SNMP_INTEGER(0); + case MPLSL3VPNVRFCONFLASTCHANGED: + return SNMP_INTEGER( + (uint32_t)l3vpn_bgp->snmp_stats->modify_time); + case MPLSL3VPNVRFCONFROWSTATUS: + return SNMP_INTEGER(1); + case MPLSL3VPNVRFCONFADMINSTATUS: + return SNMP_INTEGER(1); + case MPLSL3VPNVRFCONFSTORAGETYPE: + return SNMP_INTEGER(2); + return NULL; + } + return NULL; +} + void bgp_mpls_l3vpn_module_init(void) { + hook_register(bgp_vrf_status_changed, bgp_vrf_check_update_active); + hook_register(bgp_snmp_init_stats, bgp_init_snmp_stats); + hook_register(bgp_snmp_update_last_changed, + bgp_mpls_l3vpn_update_last_changed); REGISTER_MIB("mplsL3VpnMIB", mpls_l3vpn_variables, variable, mpls_l3vpn_oid); } diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c index 531ff4a60..f2443bd16 100644 --- a/bgpd/bgp_nb_config.c +++ b/bgpd/bgp_nb_config.c @@ -32,6 +32,8 @@ #include "bgpd/bgp_io.h" #include "bgpd/bgp_damp.h" +DEFINE_HOOK(bgp_snmp_init_stats, (struct bgp *bgp), (bgp)) + FRR_CFG_DEFAULT_ULONG(BGP_CONNECT_RETRY, { .val_ulong = 10, .match_profile = "datacenter", }, { .val_ulong = 120 }, @@ -9862,6 +9864,7 @@ static int bgp_global_afi_safi_ip_unicast_vpn_config_import_export_vpn_modify( UNSET_FLAG(bgp->af_flags[afi][safi], flag); } + hook_call(bgp_snmp_init_stats, bgp); return NB_OK; } diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c index a89c245e2..8d06a4b37 100644 --- a/bgpd/bgp_vty.c +++ b/bgpd/bgp_vty.c @@ -127,6 +127,7 @@ FRR_CFG_DEFAULT_BOOL(BGP_SUPPRESS_DUPLICATES, DEFINE_HOOK(bgp_inst_config_write, (struct bgp *bgp, struct vty *vty), (bgp, vty)) +DEFINE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp)) #define GR_NO_OPER \ "The Graceful Restart No Operation was executed as cmd same as previous one." @@ -9141,6 +9142,7 @@ DEFPY (af_label_vpn_export, vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN, afi, bgp_get_default(), bgp); + hook_call(bgp_snmp_update_last_changed, bgp); return CMD_SUCCESS; } diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c index f7c4b04ad..ca7da8070 100644 --- a/bgpd/bgp_zebra.c +++ b/bgpd/bgp_zebra.c @@ -67,6 +67,10 @@ /* All information about zebra. */ struct zclient *zclient = NULL; +/* hook to indicate vrf status change for SNMP */ +DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp), + (bgp, ifp)) + /* Can we install into zebra? */ static inline bool bgp_install_info_to_zebra(struct bgp *bgp) { @@ -212,8 +216,10 @@ static int bgp_ifp_destroy(struct interface *ifp) if (BGP_DEBUG(zebra, ZEBRA)) zlog_debug("Rx Intf del VRF %u IF %s", ifp->vrf_id, ifp->name); - if (bgp) + if (bgp) { bgp_update_interface_nbrs(bgp, ifp, NULL); + hook_call(bgp_vrf_status_changed, bgp, ifp); + } bgp_mac_del_mac_entry(ifp); @@ -243,6 +249,7 @@ static int bgp_ifp_up(struct interface *ifp) for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) bgp_nbr_connected_add(bgp, nc); + hook_call(bgp_vrf_status_changed, bgp, ifp); return 0; } @@ -297,6 +304,7 @@ static int bgp_ifp_down(struct interface *ifp) } } + hook_call(bgp_vrf_status_changed, bgp, ifp); return 0; } @@ -461,6 +469,8 @@ static int bgp_interface_vrf_update(ZAPI_CALLBACK_ARGS) for (ALL_LIST_ELEMENTS(ifp->nbr_connected, node, nnode, nc)) bgp_nbr_connected_add(bgp, nc); + + hook_call(bgp_vrf_status_changed, bgp, ifp); return 0; } @@ -2963,6 +2973,7 @@ static int bgp_ifp_create(struct interface *ifp) bgp_mac_add_mac_entry(ifp); bgp_update_interface_nbrs(bgp, ifp, ifp); + hook_call(bgp_vrf_status_changed, bgp, ifp); return 0; } diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c index edd90d704..c414c93a8 100644 --- a/bgpd/bgpd.c +++ b/bgpd/bgpd.c @@ -3704,6 +3704,7 @@ void bgp_free(struct bgp *bgp) XFREE(MTYPE_BGP, bgp->name); XFREE(MTYPE_BGP, bgp->name_pretty); + XFREE(MTYPE_BGP, bgp->snmp_stats); XFREE(MTYPE_BGP, bgp); } diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h index 65c7233e0..346d904da 100644 --- a/bgpd/bgpd.h +++ b/bgpd/bgpd.h @@ -310,6 +310,13 @@ enum bgp_link_bw_handling { RB_HEAD(bgp_es_vrf_rb_head, bgp_evpn_es_vrf); RB_PROTOTYPE(bgp_es_vrf_rb_head, bgp_evpn_es_vrf, rb_node, bgp_es_vrf_rb_cmp); +struct bgp_snmp_stats { + /* SNMP variables for mplsL3Vpn*/ + time_t creation_time; + time_t modify_time; + bool active; +}; + /* BGP instance structure. */ struct bgp { /* AS number of this BGP instance. */ @@ -363,6 +370,8 @@ struct bgp { uint32_t subgrps_deleted; } update_group_stats; + struct bgp_snmp_stats *snmp_stats; + /* BGP configuration. */ uint16_t config; #define BGP_CONFIG_CLUSTER_ID (1 << 0) @@ -2165,23 +2174,6 @@ static inline int afindex(afi_t afi, safi_t safi) } } -static inline bool is_bgp_vrf_active(struct bgp *bgp) -{ - struct vrf *vrf; - struct interface *ifp; - - /* if there is one interface in the vrf which is up then it is deemed - * active - */ - vrf = vrf_lookup_by_name(bgp->name); - if (vrf == NULL) - return false; - RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) - if (if_is_up(ifp)) - return true; - return false; -} - /* If the peer is not a peer-group but is bound to a peer-group return 1 */ static inline int peer_group_active(struct peer *peer) { @@ -2263,6 +2255,27 @@ static inline struct vrf *bgp_vrf_lookup_by_instance_type(struct bgp *bgp) return vrf; } +static inline uint32_t bgp_vrf_interfaces(struct bgp *bgp, bool active) +{ + struct vrf *vrf; + struct interface *ifp; + uint32_t count = 0; + + /* if there is one interface in the vrf which is up then it is deemed + * active + */ + vrf = bgp_vrf_lookup_by_instance_type(bgp); + if (vrf == NULL) + return 0; + RB_FOREACH (ifp, if_name_head, &vrf->ifaces_by_name) { + if (strncmp(ifp->name, bgp->name, VRF_NAMSIZ) == 0) + continue; + if (!active || if_is_up(ifp)) + count++; + } + return count; +} + /* Link BGP instance to VRF. */ static inline void bgp_vrf_link(struct bgp *bgp, struct vrf *vrf) { @@ -2300,7 +2313,11 @@ extern int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, enum bgp_instance_type inst_type); /* Hooks */ -DECLARE_HOOK(peer_status_changed, (struct peer * peer), (peer)) +DECLARE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp), + (bgp, ifp)) +DECLARE_HOOK(peer_status_changed, (struct peer *peer), (peer)) +DECLARE_HOOK(bgp_snmp_init_stats, (struct bgp *bgp), (bgp)) +DECLARE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp)) void peer_nsf_stop(struct peer *peer); #endif /* _QUAGGA_BGPD_H */ diff --git a/lib/smux.h b/lib/smux.h index 6896f0235..0efe029d3 100644 --- a/lib/smux.h +++ b/lib/smux.h @@ -106,6 +106,8 @@ extern int oid_compare(const oid *, int, const oid *, int); extern void oid2in_addr(oid[], int, struct in_addr *); extern void *oid_copy(void *, const void *, size_t); extern void oid_copy_addr(oid[], const struct in_addr *, int); +extern void oid2string(oid oid[], int len, char *string); +extern void oid_copy_str(oid oid[], const char *string, int len); #ifdef __cplusplus } diff --git a/lib/snmp.c b/lib/snmp.c index 736a3c62b..cc317d7a3 100644 --- a/lib/snmp.c +++ b/lib/snmp.c @@ -78,6 +78,34 @@ void oid_copy_addr(oid oid[], const struct in_addr *addr, int len) oid[i] = *pnt++; } +void oid2string(oid oid[], int len, char *string) +{ + int i; + uint8_t *pnt; + + if (len == 0) + return; + + pnt = (uint8_t *)string; + + for (i = 0; i < len; i++) + *pnt++ = oid[i]; +} + +void oid_copy_str(oid oid[], const char *string, int len) +{ + int i; + const uint8_t *pnt; + + if (len == 0) + return; + + pnt = (uint8_t *)string; + + for (i = 0; i < len; i++) + oid[i] = *pnt++; +} + int smux_header_generic(struct variable *v, oid *name, size_t *length, int exact, size_t *var_len, WriteMethod **write_method) { |