From a88d054d0570775ab593548d3e108f3ee1035198 Mon Sep 17 00:00:00 2001 From: christiaans Date: Thu, 7 Sep 2006 14:17:03 +0000 Subject: [PATCH] Improved TRAP interfacing. Varbinds maybe allocated at (external) trap source as wel. Added trap destination settings. --- src/core/snmp/mib2.c | 5 ++ src/core/snmp/msg_in.c | 24 +++--- src/core/snmp/msg_out.c | 165 +++++++++++++++++++++++++----------- src/include/lwip/opt.h | 7 +- src/include/lwip/snmp.h | 2 + src/include/lwip/snmp_msg.h | 19 ++++- 6 files changed, 156 insertions(+), 66 deletions(-) diff --git a/src/core/snmp/mib2.c b/src/core/snmp/mib2.c index ba047431..bed77df2 100644 --- a/src/core/snmp/mib2.c +++ b/src/core/snmp/mib2.c @@ -1919,6 +1919,11 @@ void snmp_set_snmpenableauthentraps(u8_t *value) } } +void snmp_get_snmpenableauthentraps(u8_t *value) +{ + *value = *snmpenableauthentraps_ptr; +} + void noleafs_get_object_def(u8_t ident_len, s32_t *ident, struct obj_def *od) { diff --git a/src/core/snmp/msg_in.c b/src/core/snmp/msg_in.c index c80b24e6..3f70d6f6 100644 --- a/src/core/snmp/msg_in.c +++ b/src/core/snmp/msg_in.c @@ -66,12 +66,6 @@ struct udp_pcb *snmp1_pcb = NULL; static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, struct ip_addr *addr, u16_t port); static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat); -static struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); -static void snmp_varbind_free(struct snmp_varbind *vb); -static void snmp_varbind_list_free(struct snmp_varbind_root *root); -static void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); -static struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); - /** @@ -99,6 +93,9 @@ snmp_init(void) msg_ps++; } trap_msg.pcb = snmp1_pcb; + /* The coldstart trap will only be output + if our outgoing interface is up & configured */ + snmp_coldstart_trap(); } #if 0 @@ -501,12 +498,11 @@ 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 = len; - if (strncmp(snmp_publiccommunity, m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) + if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0) { /** @todo: move this if we need to check more names */ snmp_inc_snmpinbadcommunitynames(); - - /** @todo: send authentication failure trap, if we have a trap destination */ + snmp_authfail_trap(); return ERR_ARG; } ofs += (1 + len_octets + len); @@ -826,7 +822,7 @@ snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_ return ERR_OK; } -static struct snmp_varbind* +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len) { struct snmp_varbind *vb; @@ -885,7 +881,7 @@ snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len) return vb; } -static void +void snmp_varbind_free(struct snmp_varbind *vb) { if (vb->value != NULL ) @@ -899,7 +895,7 @@ snmp_varbind_free(struct snmp_varbind *vb) mem_free(vb); } -static void +void snmp_varbind_list_free(struct snmp_varbind_root *root) { struct snmp_varbind *vb, *prev; @@ -916,7 +912,7 @@ snmp_varbind_list_free(struct snmp_varbind_root *root) root->tail = NULL; } -static void +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb) { if (root->count == 0) @@ -935,7 +931,7 @@ snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb) root->count += 1; } -static struct snmp_varbind* +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root) { struct snmp_varbind* vb; diff --git a/src/core/snmp/msg_out.c b/src/core/snmp/msg_out.c index e3cabde2..22abf082 100644 --- a/src/core/snmp/msg_out.c +++ b/src/core/snmp/msg_out.c @@ -53,10 +53,19 @@ #include "lwip/snmp_asn1.h" #include "lwip/snmp_msg.h" -/** - * TRAP message structure - * @todo turn this into an arg to snmp_create_trap ? - */ +struct snmp_trap_dst +{ + /* destination IP address in network order */ + struct ip_addr dip; + /* set to 0 when disabled, >0 when enabled */ + u8_t enable; +}; +#if (SNMP_TRAP_DESTINATIONS == 0) +#error "need at least one trap destination" +#endif +struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; + +/** TRAP message structure */ struct snmp_msg_trap trap_msg; static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len); @@ -67,7 +76,33 @@ static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p); static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs); +/** + * Sets enable switch for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param enable switch if 0 destination is disabled >0 enabled. + */ +void +snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + trap_dst[dst_idx].enable = enable; + } +} +/** + * Sets IPv4 address for this trap destination. + * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 + * @param dst IPv4 address in host order. + */ +void +snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst) +{ + if (dst_idx < SNMP_TRAP_DESTINATIONS) + { + trap_dst[dst_idx].dip.addr = htonl(dst->addr); + } +} /** * Sends a 'getresponse' message to the request originator. @@ -172,7 +207,6 @@ snmp_send_response(struct snmp_msg_pstat *m_stat) /** * Sends an generic or enterprise specific trap message. * - * @param dst points to the trap destination IPv4 address * @param generic_trap is the trap code * @param specific_trap used for enterprise traps when generic_trap == 6 * @return ERR_OK when success, ERR_MEM if we're out of memory @@ -185,63 +219,96 @@ snmp_send_response(struct snmp_msg_pstat *m_stat) * (sysObjectID) for specific traps. */ err_t -snmp_send_trap(struct ip_addr *dst, s8_t generic_trap, s32_t specific_trap) +snmp_send_trap(s8_t generic_trap, s32_t specific_trap) { + struct snmp_trap_dst *td; struct netif *dst_if; + struct ip_addr dst_ip; struct pbuf *p; - u16_t tot_len; + u16_t i,tot_len; - /* network order trap destination */ - trap_msg.dip.addr = htonl(dst->addr); - /* lookup current source address for this dst */ - dst_if = ip_route(dst); - trap_msg.sip_raw[0] = dst_if->ip_addr.addr >> 24; - trap_msg.sip_raw[1] = dst_if->ip_addr.addr >> 16; - trap_msg.sip_raw[2] = dst_if->ip_addr.addr >> 8; - trap_msg.sip_raw[3] = dst_if->ip_addr.addr; - trap_msg.gen_trap = generic_trap; - trap_msg.spc_trap = specific_trap; - if (generic_trap == 6) + for (i=0, td = &trap_dst[0]; ienable != 0) && (td->dip.addr != 0)) + { + /* network order trap destination */ + trap_msg.dip.addr = td->dip.addr; + /* lookup current source address for this dst */ + dst_if = ip_route(&td->dip); + dst_ip.addr = ntohl(dst_if->ip_addr.addr); + trap_msg.sip_raw[0] = dst_ip.addr >> 24; + trap_msg.sip_raw[1] = dst_ip.addr >> 16; + trap_msg.sip_raw[2] = dst_ip.addr >> 8; + trap_msg.sip_raw[3] = dst_ip.addr; + trap_msg.gen_trap = generic_trap; + trap_msg.spc_trap = specific_trap; + if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) + { + /* enterprise-Specific trap */ + snmp_get_sysobjid_ptr(&trap_msg.enterprise); + } + else + { + /* generic (MIB-II) trap */ + snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); + } + snmp_get_sysuptime(&trap_msg.ts); - /* pass 0, calculate length fields */ - tot_len = snmp_varbind_list_sum(&trap_msg.outvb); - tot_len = snmp_trap_header_sum(&trap_msg, tot_len); + /* pass 0, calculate length fields */ + tot_len = snmp_varbind_list_sum(&trap_msg.outvb); + tot_len = snmp_trap_header_sum(&trap_msg, tot_len); - /* allocate pbuf(s) */ - p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); - if (p != NULL) - { - u16_t ofs; + /* allocate pbuf(s) */ + p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); + if (p != NULL) + { + u16_t ofs; - /* pass 1, encode packet ino the pbuf(s) */ - ofs = snmp_trap_header_enc(&trap_msg, p); - snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); + /* pass 1, encode packet ino the pbuf(s) */ + ofs = snmp_trap_header_enc(&trap_msg, p); + snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); - snmp_inc_snmpouttraps(); - snmp_inc_snmpoutpkts(); + snmp_inc_snmpouttraps(); + snmp_inc_snmpoutpkts(); - /** connect to the TRAP destination */ - udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT); - udp_send(trap_msg.pcb, p); - /** disassociate remote address and port with this pcb */ - udp_disconnect(trap_msg.pcb); + /** connect to the TRAP destination */ + udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT); + udp_send(trap_msg.pcb, p); + /** disassociate remote address and port with this pcb */ + udp_disconnect(trap_msg.pcb); - pbuf_free(p); - return ERR_OK; + pbuf_free(p); + } + else + { + return ERR_MEM; + } + } + td++; } - else + return ERR_OK; +} + +void +snmp_coldstart_trap(void) +{ + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_COLDSTART, 0); +} + +void +snmp_authfail_trap(void) +{ + u8_t enable; + snmp_get_snmpenableauthentraps(&enable); + if (enable == 1) { - return ERR_MEM; + trap_msg.outvb.head = NULL; + trap_msg.outvb.tail = NULL; + trap_msg.outvb.count = 0; + snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, 0); } } diff --git a/src/include/lwip/opt.h b/src/include/lwip/opt.h index eeb3a57e..c5e21f76 100644 --- a/src/include/lwip/opt.h +++ b/src/include/lwip/opt.h @@ -250,11 +250,14 @@ a lot of data that needs to be copied, this should be set high. */ #endif /* ---------- SNMP options ---------- */ -/** @todo SNMP isn't functional yet. - @note UDP must be available for SNMP transport */ +/** @note UDP must be available for SNMP transport */ #ifndef LWIP_SNMP #define LWIP_SNMP 0 #endif +/** @note At least one trap destination is required */ +#ifndef SNMP_TRAP_DESTINATIONS +#define SNMP_TRAP_DESTINATIONS 1 +#endif #ifndef SNMP_PRIVATE_MIB #define SNMP_PRIVATE_MIB 0 diff --git a/src/include/lwip/snmp.h b/src/include/lwip/snmp.h index 12ae7b49..95145ce0 100644 --- a/src/include/lwip/snmp.h +++ b/src/include/lwip/snmp.h @@ -175,6 +175,7 @@ void snmp_inc_snmpoutgetresponses(void); void snmp_inc_snmpouttraps(void); void snmp_get_snmpgrpid_ptr(struct snmp_obj_id **oid); void snmp_set_snmpenableauthentraps(u8_t *value); +void snmp_get_snmpenableauthentraps(u8_t *value); /* LWIP_SNMP support not available */ /* define everything to be empty */ @@ -301,6 +302,7 @@ void snmp_set_snmpenableauthentraps(u8_t *value); #define snmp_inc_snmpouttraps() #define snmp_get_snmpgrpid_ptr(oid) #define snmp_set_snmpenableauthentraps(value) +#define snmp_get_snmpenableauthentraps(value) #endif diff --git a/src/include/lwip/snmp_msg.h b/src/include/lwip/snmp_msg.h index de51e10d..af703590 100644 --- a/src/include/lwip/snmp_msg.h +++ b/src/include/lwip/snmp_msg.h @@ -53,6 +53,11 @@ #define SNMP_ES_READONLY 4 #define SNMP_ES_GENERROR 5 +#define SNMP_GENTRAP_COLDSTART 0 +#define SNMP_GENTRAP_WARMSTART 1 +#define SNMP_GENTRAP_AUTHFAIL 4 +#define SNMP_GENTRAP_ENTERPRISESPC 6 + struct snmp_varbind { /* next pointer, NULL for last in list */ @@ -264,9 +269,21 @@ extern struct snmp_msg_trap trap_msg; /** Agent setup, start listening to port 161. */ void snmp_init(void); +void snmp_trap_dst_enable(u8_t dst_idx, u8_t enable); +void snmp_trap_dst_ip_set(u8_t dst_idx, struct ip_addr *dst); + +/** Varbind-list functions. */ +struct snmp_varbind* snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len); +void snmp_varbind_free(struct snmp_varbind *vb); +void snmp_varbind_list_free(struct snmp_varbind_root *root); +void snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb); +struct snmp_varbind* snmp_varbind_tail_remove(struct snmp_varbind_root *root); + /** Handles internal/external events. */ void snmp_msg_event(struct snmp_msg_pstat *msg_ps); err_t snmp_send_response(struct snmp_msg_pstat *m_stat); -err_t snmp_send_trap(struct ip_addr *dst, s8_t generic_trap, s32_t specific_trap); +err_t snmp_send_trap(s8_t generic_trap, s32_t specific_trap); +void snmp_coldstart_trap(void); +void snmp_authfail_trap(void); #endif