From 0d18516af8196721f9cb9205d7d967b0765b8b85 Mon Sep 17 00:00:00 2001 From: sg Date: Sat, 14 Feb 2015 15:44:32 +0100 Subject: [PATCH] added support for write-access community and dedicated community for sending traps --- CHANGELOG | 6 ++- src/core/snmp/msg_in.c | 86 +++++++++++++++++++++++++++++++++---- src/core/snmp/msg_out.c | 8 +++- src/include/lwip/opt.h | 31 +++++++++++++ src/include/lwip/snmp.h | 6 +++ src/include/lwip/snmp_msg.h | 6 +++ 6 files changed, 132 insertions(+), 11 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index af4263f7..e4018d9a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,6 +6,10 @@ HISTORY ++ New features: + 2015-02-14: Simon Goldschmidt + * opt.h, snmp*: added support for write-access community and dedicated + community for sending traps + 2015-02-13: Simon Goldschmidt * opt.h, memp.c: added hook LWIP_HOOK_MEMP_AVAILABLE() to get informed when a memp pool was empty and an item is now available @@ -179,7 +183,7 @@ HISTORY ++ Bugfixes: - 2015-02-15: patches by Freddie Chopin + 2015-02-14: patches by Freddie Chopin * snmp*: made community writable, fixed some const pointers 2015-02-13: Simon Goldschmidt diff --git a/src/core/snmp/msg_in.c b/src/core/snmp/msg_in.c index 9ee5586a..08c5b346 100644 --- a/src/core/snmp/msg_in.c +++ b/src/core/snmp/msg_in.c @@ -51,7 +51,13 @@ /** SNMP v1 == 0 */ const s32_t snmp_version = 0; /** SNMP community string */ -const char *snmp_community = "public"; +const char *snmp_community = SNMP_COMMUNITY; +#if SNMP_COMMUNITY_EXT +/** SNMP community string for write access */ +const char *snmp_community_write = SNMP_COMMUNITY_WRITE; +/** SNMP community string for sending traps */ +const char *snmp_community_trap = SNMP_COMMUNITY_TRAP; +#endif /* SNMP_COMMUNITY_EXT */ /* statically allocated buffers for SNMP_CONCURRENT_REQUESTS */ struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS]; @@ -126,6 +132,56 @@ snmp_set_community(const char * const community) snmp_community = community; } +#if SNMP_COMMUNITY_EXT +/** + * Returns current SNMP write-access community string. + * @return current SNMP write-access community string + */ +const char * +snmp_get_community_write(void) +{ + return snmp_community_write; +} + +/** + * Returns current SNMP community string used for sending traps. + * @return current SNMP community string used for sending traps + */ +const char * +snmp_get_community_trap(void) +{ + return snmp_community_trap; +} + +/** + * Sets SNMP community string for write-access. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new write-access community string + */ +void +snmp_set_community_write(const char * const community) +{ + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_COMMUNITY_STR_LEN); + snmp_community_write = community; +} + +/** + * Sets SNMP community string used for sending traps. + * The string itself (its storage) must be valid throughout the whole life of + * program (or until it is changed to sth else). + * + * @param community is a pointer to new trap community string + */ +void +snmp_set_community_trap(const char * const community) +{ + LWIP_ASSERT("community string is too long!", strlen(community) <= SNMP_COMMUNITY_STR_LEN); + snmp_community_trap = community; +} +#endif /* SNMP_COMMUNITY_EXT */ + static void snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error) { @@ -998,15 +1054,29 @@ snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN)); m_stat->community[len] = 0; m_stat->com_strlen = (u8_t)len; - if (strncmp(snmp_community, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) - { - /** @todo: move this if we need to check more names */ - snmp_inc_snmpinbadcommunitynames(); - snmp_authfail_trap(); - return ERR_ARG; - } ofs += (1 + len_octets + len); snmp_asn1_dec_type(p, ofs, &type); +#if SNMP_COMMUNITY_EXT + if (strncmp(snmp_community_write, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) + { + /* community does not match the write-access community, check if this is a SetRequest */ + if (type == (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ)) + { + /* wrong community for SetRequest PDU */ + snmp_inc_snmpinbadcommunitynames(); + snmp_authfail_trap(); + return ERR_ARG; + } +#else /* SNMP_COMMUNITY_EXT */ + { +#endif /* SNMP_COMMUNITY_EXT */ + if (strncmp(snmp_community, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) + { + snmp_inc_snmpinbadcommunitynames(); + snmp_authfail_trap(); + return ERR_ARG; + } + } derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len); if (derr != ERR_OK) { diff --git a/src/core/snmp/msg_out.c b/src/core/snmp/msg_out.c index 358cf6b7..ff74e50c 100644 --- a/src/core/snmp/msg_out.c +++ b/src/core/snmp/msg_out.c @@ -54,6 +54,10 @@ #include +#if !SNMP_COMMUNITY_EXT +#define snmp_community_trap snmp_community +#endif + struct snmp_trap_dst { /* destination IP address in network order */ @@ -400,7 +404,7 @@ snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); tot_len += 1 + thl->pdulenlen; - thl->comlen = strlen(snmp_community); + thl->comlen = strlen(snmp_community_trap); snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); tot_len += 1 + thl->comlenlen + thl->comlen; @@ -567,7 +571,7 @@ snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) ofs += 1; snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); ofs += m_trap->thl.comlenlen; - snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_community[0]); + snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_community_trap[0]); ofs += m_trap->thl.comlen; snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index bd834a40..c8c1f119 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -872,6 +872,37 @@ #define SNMP_MAX_VALUE_SIZE LWIP_MAX((SNMP_MAX_OCTET_STRING_LEN)+1, sizeof(s32_t)*(SNMP_MAX_TREE_DEPTH)) #endif +/** + * The snmp read-access community. Used for write-access and traps, too + * unless SNMP_COMMUNITY_WRITE or SNMP_COMMUNITY_TRAP are enabled, respectively. + */ +#ifndef SNMP_COMMUNITY +#define SNMP_COMMUNITY "public" +#endif + +/** + * Set this to 1 to enable support for dedicated write-access and trap communities. + */ +#ifndef SNMP_COMMUNITY_EXT +#define SNMP_COMMUNITY_EXT +#endif + +#if SNMP_COMMUNITY_EXT +/** + * The snmp write-access community. + */ +#ifndef SNMP_COMMUNITY_WRITE +#define SNMP_COMMUNITY_WRITE "private" +#endif + +/** + * The snmp community used for sending traps. + */ +#ifndef SNMP_COMMUNITY_TRAP +#define SNMP_COMMUNITY_TRAP "public" +#endif +#endif /* SNMP_COMMUNITY_EXT */ + /* ---------------------------------- ---------- IGMP options ---------- diff --git a/src/include/lwip/snmp.h b/src/include/lwip/snmp.h index f9a52e2f..ba84e2e7 100644 --- a/src/include/lwip/snmp.h +++ b/src/include/lwip/snmp.h @@ -99,6 +99,12 @@ struct snmp_obj_id const char * snmp_get_community(void); void snmp_set_community(const char * const community); +#if SNMP_COMMUNITY_EXT +const char * snmp_get_community_write(void); +const char * snmp_get_community_trap(void); +void snmp_set_community_write(const char * const community); +void snmp_set_community_trap(const char * const community); +#endif /* SNMP_COMMUNITY_EXT /* system */ void snmp_set_sysdescr(const u8_t* str, const u8_t* len); diff --git a/src/include/lwip/snmp_msg.h b/src/include/lwip/snmp_msg.h index 01d45ac8..847ddd9b 100644 --- a/src/include/lwip/snmp_msg.h +++ b/src/include/lwip/snmp_msg.h @@ -284,6 +284,12 @@ struct snmp_msg_trap extern const s32_t snmp_version; /** Agent community string */ extern const char *snmp_community; +#if SNMP_COMMUNITY_EXT +/** Agent community string for write access */ +extern const char *snmp_community_write; +/** Agent community string for sending traps */ +extern const char *snmp_community_trap; +#endif /* SNMP_COMMUNITY_EXT */ extern struct snmp_msg_trap trap_msg;