Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
lwip_snmp_traps.c
00001 /** 00002 * @file 00003 * SNMPv1 traps implementation. 00004 */ 00005 00006 /* 00007 * Copyright (c) 2001-2004 Swedish Institute of Computer Science. 00008 * All rights reserved. 00009 * 00010 * Redistribution and use in source and binary forms, with or without modification, 00011 * are permitted provided that the following conditions are met: 00012 * 00013 * 1. Redistributions of source code must retain the above copyright notice, 00014 * this list of conditions and the following disclaimer. 00015 * 2. Redistributions in binary form must reproduce the above copyright notice, 00016 * this list of conditions and the following disclaimer in the documentation 00017 * and/or other materials provided with the distribution. 00018 * 3. The name of the author may not be used to endorse or promote products 00019 * derived from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00022 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00024 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00025 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00026 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00027 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00028 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00029 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00030 * OF SUCH DAMAGE. 00031 * 00032 * This file is part of the lwIP TCP/IP stack. 00033 * 00034 * Author: Martin Hentschel 00035 * Christiaan Simons <christiaan.simons@axon.tv> 00036 * 00037 */ 00038 00039 #include "lwip/apps/snmp_opts.h" 00040 00041 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ 00042 00043 #include <string.h> 00044 00045 #include "lwip/snmp.h" 00046 #include "lwip/sys.h" 00047 #include "lwip/apps/snmp.h" 00048 #include "lwip/apps/snmp_core.h" 00049 #include "lwip/prot/iana.h" 00050 #include "snmp_msg.h" 00051 #include "snmp_asn1.h" 00052 #include "snmp_core_priv.h" 00053 00054 struct snmp_msg_trap { 00055 /* source enterprise ID (sysObjectID) */ 00056 const struct snmp_obj_id *enterprise; 00057 /* source IP address, raw network order format */ 00058 ip_addr_t sip; 00059 /* generic trap code */ 00060 u32_t gen_trap; 00061 /* specific trap code */ 00062 u32_t spc_trap; 00063 /* timestamp */ 00064 u32_t ts; 00065 /* snmp_version */ 00066 u32_t snmp_version; 00067 00068 /* output trap lengths used in ASN encoding */ 00069 /* encoding pdu length */ 00070 u16_t pdulen; 00071 /* encoding community length */ 00072 u16_t comlen; 00073 /* encoding sequence length */ 00074 u16_t seqlen; 00075 /* encoding varbinds sequence length */ 00076 u16_t vbseqlen; 00077 }; 00078 00079 static u16_t snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds); 00080 static u16_t snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len); 00081 static err_t snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); 00082 static err_t snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); 00083 00084 #define BUILD_EXEC(code) \ 00085 if ((code) != ERR_OK) { \ 00086 LWIP_DEBUGF(SNMP_DEBUG, ("SNMP error during creation of outbound trap frame!")); \ 00087 return ERR_ARG; \ 00088 } 00089 00090 /** Agent community string for sending traps */ 00091 extern const char *snmp_community_trap; 00092 00093 void *snmp_traps_handle; 00094 00095 struct snmp_trap_dst { 00096 /* destination IP address in network order */ 00097 ip_addr_t dip; 00098 /* set to 0 when disabled, >0 when enabled */ 00099 u8_t enable; 00100 }; 00101 static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; 00102 00103 static u8_t snmp_auth_traps_enabled = 0; 00104 00105 /** 00106 * @ingroup snmp_traps 00107 * Sets enable switch for this trap destination. 00108 * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 00109 * @param enable switch if 0 destination is disabled >0 enabled. 00110 */ 00111 void 00112 snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) 00113 { 00114 LWIP_ASSERT_CORE_LOCKED(); 00115 if (dst_idx < SNMP_TRAP_DESTINATIONS) { 00116 trap_dst[dst_idx].enable = enable; 00117 } 00118 } 00119 00120 /** 00121 * @ingroup snmp_traps 00122 * Sets IPv4 address for this trap destination. 00123 * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 00124 * @param dst IPv4 address in host order. 00125 */ 00126 void 00127 snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) 00128 { 00129 LWIP_ASSERT_CORE_LOCKED(); 00130 if (dst_idx < SNMP_TRAP_DESTINATIONS) { 00131 ip_addr_set(&trap_dst[dst_idx].dip, dst); 00132 } 00133 } 00134 00135 /** 00136 * @ingroup snmp_traps 00137 * Enable/disable authentication traps 00138 */ 00139 void 00140 snmp_set_auth_traps_enabled(u8_t enable) 00141 { 00142 snmp_auth_traps_enabled = enable; 00143 } 00144 00145 /** 00146 * @ingroup snmp_traps 00147 * Get authentication traps enabled state 00148 */ 00149 u8_t 00150 snmp_get_auth_traps_enabled(void) 00151 { 00152 return snmp_auth_traps_enabled; 00153 } 00154 00155 00156 /** 00157 * @ingroup snmp_traps 00158 * Sends a generic or enterprise specific trap message. 00159 * 00160 * @param eoid points to enterprise object identifier 00161 * @param generic_trap is the trap code 00162 * @param specific_trap used for enterprise traps when generic_trap == 6 00163 * @param varbinds linked list of varbinds to be sent 00164 * @return ERR_OK when success, ERR_MEM if we're out of memory 00165 * 00166 * @note the use of the enterprise identifier field 00167 * is per RFC1215. 00168 * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps 00169 * and .iso.org.dod.internet.private.enterprises.yourenterprise 00170 * (sysObjectID) for specific traps. 00171 */ 00172 err_t 00173 snmp_send_trap(const struct snmp_obj_id *eoid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) 00174 { 00175 struct snmp_msg_trap trap_msg; 00176 struct snmp_trap_dst *td; 00177 struct pbuf *p; 00178 u16_t i, tot_len; 00179 err_t err = ERR_OK; 00180 00181 LWIP_ASSERT_CORE_LOCKED(); 00182 00183 trap_msg.snmp_version = 0; 00184 00185 for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { 00186 if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { 00187 /* lookup current source address for this dst */ 00188 if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { 00189 if (eoid == NULL) { 00190 trap_msg.enterprise = snmp_get_device_enterprise_oid(); 00191 } else { 00192 trap_msg.enterprise = eoid; 00193 } 00194 00195 trap_msg.gen_trap = generic_trap; 00196 if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { 00197 trap_msg.spc_trap = specific_trap; 00198 } else { 00199 trap_msg.spc_trap = 0; 00200 } 00201 00202 MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); 00203 00204 /* pass 0, calculate length fields */ 00205 tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); 00206 tot_len = snmp_trap_header_sum(&trap_msg, tot_len); 00207 00208 /* allocate pbuf(s) */ 00209 p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); 00210 if (p != NULL) { 00211 struct snmp_pbuf_stream pbuf_stream; 00212 snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); 00213 00214 /* pass 1, encode packet into the pbuf(s) */ 00215 snmp_trap_header_enc(&trap_msg, &pbuf_stream); 00216 snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); 00217 00218 snmp_stats.outtraps++; 00219 snmp_stats.outpkts++; 00220 00221 /** send to the TRAP destination */ 00222 snmp_sendto(snmp_traps_handle, p, &td->dip, LWIP_IANA_PORT_SNMP_TRAP); 00223 pbuf_free(p); 00224 } else { 00225 err = ERR_MEM; 00226 } 00227 } else { 00228 /* routing error */ 00229 err = ERR_RTE; 00230 } 00231 } 00232 } 00233 return err; 00234 } 00235 00236 /** 00237 * @ingroup snmp_traps 00238 * Send generic SNMP trap 00239 */ 00240 err_t 00241 snmp_send_trap_generic(s32_t generic_trap) 00242 { 00243 static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; 00244 return snmp_send_trap(&oid, generic_trap, 0, NULL); 00245 } 00246 00247 /** 00248 * @ingroup snmp_traps 00249 * Send specific SNMP trap with variable bindings 00250 */ 00251 err_t 00252 snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) 00253 { 00254 return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); 00255 } 00256 00257 /** 00258 * @ingroup snmp_traps 00259 * Send coldstart trap 00260 */ 00261 void 00262 snmp_coldstart_trap(void) 00263 { 00264 snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); 00265 } 00266 00267 /** 00268 * @ingroup snmp_traps 00269 * Send authentication failure trap (used internally by agent) 00270 */ 00271 void 00272 snmp_authfail_trap(void) 00273 { 00274 if (snmp_auth_traps_enabled != 0) { 00275 snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); 00276 } 00277 } 00278 00279 static u16_t 00280 snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) 00281 { 00282 struct snmp_varbind *varbind; 00283 u16_t tot_len; 00284 u8_t tot_len_len; 00285 00286 tot_len = 0; 00287 varbind = varbinds; 00288 while (varbind != NULL) { 00289 struct snmp_varbind_len len; 00290 00291 if (snmp_varbind_length(varbind, &len) == ERR_OK) { 00292 tot_len += 1 + len.vb_len_len + len.vb_value_len; 00293 } 00294 00295 varbind = varbind->next; 00296 } 00297 00298 trap->vbseqlen = tot_len; 00299 snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); 00300 tot_len += 1 + tot_len_len; 00301 00302 return tot_len; 00303 } 00304 00305 /** 00306 * Sums trap header field lengths from tail to head and 00307 * returns trap_header_lengths for second encoding pass. 00308 * 00309 * @param trap Trap message 00310 * @param vb_len varbind-list length 00311 * @return the required length for encoding the trap header 00312 */ 00313 static u16_t 00314 snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) 00315 { 00316 u16_t tot_len; 00317 u16_t len; 00318 u8_t lenlen; 00319 00320 tot_len = vb_len; 00321 00322 snmp_asn1_enc_u32t_cnt(trap->ts, &len); 00323 snmp_asn1_enc_length_cnt(len, &lenlen); 00324 tot_len += 1 + len + lenlen; 00325 00326 snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); 00327 snmp_asn1_enc_length_cnt(len, &lenlen); 00328 tot_len += 1 + len + lenlen; 00329 00330 snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); 00331 snmp_asn1_enc_length_cnt(len, &lenlen); 00332 tot_len += 1 + len + lenlen; 00333 00334 if (IP_IS_V6_VAL(trap->sip)) { 00335 #if LWIP_IPV6 00336 len = sizeof(ip_2_ip6(&trap->sip)->addr); 00337 #endif 00338 } else { 00339 #if LWIP_IPV4 00340 len = sizeof(ip_2_ip4(&trap->sip)->addr); 00341 #endif 00342 } 00343 snmp_asn1_enc_length_cnt(len, &lenlen); 00344 tot_len += 1 + len + lenlen; 00345 00346 snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); 00347 snmp_asn1_enc_length_cnt(len, &lenlen); 00348 tot_len += 1 + len + lenlen; 00349 00350 trap->pdulen = tot_len; 00351 snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); 00352 tot_len += 1 + lenlen; 00353 00354 trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); 00355 snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); 00356 tot_len += 1 + lenlen + trap->comlen; 00357 00358 snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); 00359 snmp_asn1_enc_length_cnt(len, &lenlen); 00360 tot_len += 1 + len + lenlen; 00361 00362 trap->seqlen = tot_len; 00363 snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); 00364 tot_len += 1 + lenlen; 00365 00366 return tot_len; 00367 } 00368 00369 static err_t 00370 snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) 00371 { 00372 struct snmp_asn1_tlv tlv; 00373 struct snmp_varbind *varbind; 00374 00375 varbind = varbinds; 00376 00377 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); 00378 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00379 00380 while (varbind != NULL) { 00381 BUILD_EXEC( snmp_append_outbound_varbind(pbuf_stream, varbind) ); 00382 00383 varbind = varbind->next; 00384 } 00385 00386 return ERR_OK; 00387 } 00388 00389 /** 00390 * Encodes trap header from head to tail. 00391 */ 00392 static err_t 00393 snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) 00394 { 00395 struct snmp_asn1_tlv tlv; 00396 00397 /* 'Message' sequence */ 00398 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); 00399 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00400 00401 /* version */ 00402 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 00403 snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); 00404 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00405 BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version) ); 00406 00407 /* community */ 00408 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); 00409 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00410 BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen) ); 00411 00412 /* 'PDU' sequence */ 00413 SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); 00414 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00415 00416 /* object ID */ 00417 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); 00418 snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); 00419 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00420 BUILD_EXEC( snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len) ); 00421 00422 /* IP addr */ 00423 if (IP_IS_V6_VAL(trap->sip)) { 00424 #if LWIP_IPV6 00425 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); 00426 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00427 BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)) ); 00428 #endif 00429 } else { 00430 #if LWIP_IPV4 00431 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); 00432 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00433 BUILD_EXEC( snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)) ); 00434 #endif 00435 } 00436 00437 /* trap length */ 00438 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 00439 snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); 00440 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00441 BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap) ); 00442 00443 /* specific trap */ 00444 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 00445 snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); 00446 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00447 BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap) ); 00448 00449 /* timestamp */ 00450 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); 00451 snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); 00452 BUILD_EXEC( snmp_ans1_enc_tlv(pbuf_stream, &tlv) ); 00453 BUILD_EXEC( snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts) ); 00454 00455 return ERR_OK; 00456 } 00457 00458 #endif /* LWIP_SNMP */
Generated on Tue Jul 12 2022 13:54:30 by
