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.
Fork of mbed-os by
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 "snmp_msg.h" 00050 #include "snmp_asn1.h" 00051 #include "snmp_core_priv.h" 00052 00053 struct snmp_msg_trap 00054 { 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 void snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream); 00082 static void snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds); 00083 00084 /** Agent community string for sending traps */ 00085 extern const char *snmp_community_trap; 00086 00087 void* snmp_traps_handle; 00088 00089 struct snmp_trap_dst 00090 { 00091 /* destination IP address in network order */ 00092 ip_addr_t dip; 00093 /* set to 0 when disabled, >0 when enabled */ 00094 u8_t enable; 00095 }; 00096 static struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; 00097 00098 static u8_t snmp_auth_traps_enabled = 0; 00099 00100 /** 00101 * @ingroup snmp_traps 00102 * Sets enable switch for this trap destination. 00103 * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 00104 * @param enable switch if 0 destination is disabled >0 enabled. 00105 */ 00106 void 00107 snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) 00108 { 00109 if (dst_idx < SNMP_TRAP_DESTINATIONS) { 00110 trap_dst[dst_idx].enable = enable; 00111 } 00112 } 00113 00114 /** 00115 * @ingroup snmp_traps 00116 * Sets IPv4 address for this trap destination. 00117 * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 00118 * @param dst IPv4 address in host order. 00119 */ 00120 void 00121 snmp_trap_dst_ip_set(u8_t dst_idx, const ip_addr_t *dst) 00122 { 00123 if (dst_idx < SNMP_TRAP_DESTINATIONS) { 00124 ip_addr_set(&trap_dst[dst_idx].dip, dst); 00125 } 00126 } 00127 00128 /** 00129 * @ingroup snmp_traps 00130 * Enable/disable authentication traps 00131 */ 00132 void 00133 snmp_set_auth_traps_enabled(u8_t enable) 00134 { 00135 snmp_auth_traps_enabled = enable; 00136 } 00137 00138 /** 00139 * @ingroup snmp_traps 00140 * Get authentication traps enabled state 00141 */ 00142 u8_t 00143 snmp_get_auth_traps_enabled(void) 00144 { 00145 return snmp_auth_traps_enabled; 00146 } 00147 00148 00149 /** 00150 * Sends an generic or enterprise specific trap message. 00151 * 00152 * @param generic_trap is the trap code 00153 * @param eoid points to enterprise object identifier 00154 * @param specific_trap used for enterprise traps when generic_trap == 6 00155 * @return ERR_OK when success, ERR_MEM if we're out of memory 00156 * 00157 * @note the use of the enterprise identifier field 00158 * is per RFC1215. 00159 * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps 00160 * and .iso.org.dod.internet.private.enterprises.yourenterprise 00161 * (sysObjectID) for specific traps. 00162 */ 00163 static err_t 00164 snmp_send_trap(const struct snmp_obj_id *device_enterprise_oid, s32_t generic_trap, s32_t specific_trap, struct snmp_varbind *varbinds) 00165 { 00166 struct snmp_msg_trap trap_msg; 00167 struct snmp_trap_dst *td; 00168 struct pbuf *p; 00169 u16_t i, tot_len; 00170 err_t err = ERR_OK; 00171 00172 trap_msg.snmp_version = 0; 00173 00174 for (i = 0, td = &trap_dst[0]; i < SNMP_TRAP_DESTINATIONS; i++, td++) { 00175 if ((td->enable != 0) && !ip_addr_isany(&td->dip)) { 00176 /* lookup current source address for this dst */ 00177 if (snmp_get_local_ip_for_dst(snmp_traps_handle, &td->dip, &trap_msg.sip)) { 00178 if (device_enterprise_oid == NULL) { 00179 trap_msg.enterprise = snmp_get_device_enterprise_oid(); 00180 } else { 00181 trap_msg.enterprise = device_enterprise_oid; 00182 } 00183 00184 trap_msg.gen_trap = generic_trap; 00185 if (generic_trap == SNMP_GENTRAP_ENTERPRISE_SPECIFIC) { 00186 trap_msg.spc_trap = specific_trap; 00187 } else { 00188 trap_msg.spc_trap = 0; 00189 } 00190 00191 MIB2_COPY_SYSUPTIME_TO(&trap_msg.ts); 00192 00193 /* pass 0, calculate length fields */ 00194 tot_len = snmp_trap_varbind_sum(&trap_msg, varbinds); 00195 tot_len = snmp_trap_header_sum(&trap_msg, tot_len); 00196 00197 /* allocate pbuf(s) */ 00198 p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_RAM); 00199 if (p != NULL) { 00200 struct snmp_pbuf_stream pbuf_stream; 00201 snmp_pbuf_stream_init(&pbuf_stream, p, 0, tot_len); 00202 00203 /* pass 1, encode packet ino the pbuf(s) */ 00204 snmp_trap_header_enc(&trap_msg, &pbuf_stream); 00205 snmp_trap_varbind_enc(&trap_msg, &pbuf_stream, varbinds); 00206 00207 snmp_stats.outtraps++; 00208 snmp_stats.outpkts++; 00209 00210 /** send to the TRAP destination */ 00211 snmp_sendto(snmp_traps_handle, p, &td->dip, SNMP_TRAP_PORT); 00212 pbuf_free(p); 00213 } else { 00214 err = ERR_MEM; 00215 } 00216 } else { 00217 /* routing error */ 00218 err = ERR_RTE; 00219 } 00220 } 00221 } 00222 return err; 00223 } 00224 00225 /** 00226 * @ingroup snmp_traps 00227 * Send generic SNMP trap 00228 */ 00229 err_t 00230 snmp_send_trap_generic(s32_t generic_trap) 00231 { 00232 static const struct snmp_obj_id oid = { 7, { 1, 3, 6, 1, 2, 1, 11 } }; 00233 return snmp_send_trap(&oid, generic_trap, 0, NULL); 00234 } 00235 00236 /** 00237 *@ingroup snmp_traps 00238 * Send specific SNMP trap with variable bindings 00239 */ 00240 err_t 00241 snmp_send_trap_specific(s32_t specific_trap, struct snmp_varbind *varbinds) 00242 { 00243 return snmp_send_trap(NULL, SNMP_GENTRAP_ENTERPRISE_SPECIFIC, specific_trap, varbinds); 00244 } 00245 00246 /** 00247 * @ingroup snmp_traps 00248 * Send coldstart trap 00249 */ 00250 void 00251 snmp_coldstart_trap(void) 00252 { 00253 snmp_send_trap_generic(SNMP_GENTRAP_COLDSTART); 00254 } 00255 00256 /** 00257 * @ingroup snmp_traps 00258 * Send authentication failure trap (used internally by agent) 00259 */ 00260 void 00261 snmp_authfail_trap(void) 00262 { 00263 if (snmp_auth_traps_enabled != 0) { 00264 snmp_send_trap_generic(SNMP_GENTRAP_AUTH_FAILURE); 00265 } 00266 } 00267 00268 static u16_t 00269 snmp_trap_varbind_sum(struct snmp_msg_trap *trap, struct snmp_varbind *varbinds) 00270 { 00271 struct snmp_varbind *varbind; 00272 u16_t tot_len; 00273 u8_t tot_len_len; 00274 00275 tot_len = 0; 00276 varbind = varbinds; 00277 while (varbind != NULL) { 00278 struct snmp_varbind_len len; 00279 00280 if (snmp_varbind_length(varbind, &len) == ERR_OK) { 00281 tot_len += 1 + len.vb_len_len + len.vb_value_len; 00282 } 00283 00284 varbind = varbind->next; 00285 } 00286 00287 trap->vbseqlen = tot_len; 00288 snmp_asn1_enc_length_cnt(trap->vbseqlen, &tot_len_len); 00289 tot_len += 1 + tot_len_len; 00290 00291 return tot_len; 00292 } 00293 00294 /** 00295 * Sums trap header field lengths from tail to head and 00296 * returns trap_header_lengths for second encoding pass. 00297 * 00298 * @param vb_len varbind-list length 00299 * @param thl points to returned header lengths 00300 * @return the required length for encoding the trap header 00301 */ 00302 static u16_t 00303 snmp_trap_header_sum(struct snmp_msg_trap *trap, u16_t vb_len) 00304 { 00305 u16_t tot_len; 00306 u16_t len; 00307 u8_t lenlen; 00308 00309 tot_len = vb_len; 00310 00311 snmp_asn1_enc_u32t_cnt(trap->ts, &len); 00312 snmp_asn1_enc_length_cnt(len, &lenlen); 00313 tot_len += 1 + len + lenlen; 00314 00315 snmp_asn1_enc_s32t_cnt(trap->spc_trap, &len); 00316 snmp_asn1_enc_length_cnt(len, &lenlen); 00317 tot_len += 1 + len + lenlen; 00318 00319 snmp_asn1_enc_s32t_cnt(trap->gen_trap, &len); 00320 snmp_asn1_enc_length_cnt(len, &lenlen); 00321 tot_len += 1 + len + lenlen; 00322 00323 if (IP_IS_V6_VAL(trap->sip)) { 00324 #if LWIP_IPV6 00325 len = sizeof(ip_2_ip6(&trap->sip)->addr); 00326 #endif 00327 } else { 00328 #if LWIP_IPV4 00329 len = sizeof(ip_2_ip4(&trap->sip)->addr); 00330 #endif 00331 } 00332 snmp_asn1_enc_length_cnt(len, &lenlen); 00333 tot_len += 1 + len + lenlen; 00334 00335 snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &len); 00336 snmp_asn1_enc_length_cnt(len, &lenlen); 00337 tot_len += 1 + len + lenlen; 00338 00339 trap->pdulen = tot_len; 00340 snmp_asn1_enc_length_cnt(trap->pdulen, &lenlen); 00341 tot_len += 1 + lenlen; 00342 00343 trap->comlen = (u16_t)LWIP_MIN(strlen(snmp_community_trap), 0xFFFF); 00344 snmp_asn1_enc_length_cnt(trap->comlen, &lenlen); 00345 tot_len += 1 + lenlen + trap->comlen; 00346 00347 snmp_asn1_enc_s32t_cnt(trap->snmp_version, &len); 00348 snmp_asn1_enc_length_cnt(len, &lenlen); 00349 tot_len += 1 + len + lenlen; 00350 00351 trap->seqlen = tot_len; 00352 snmp_asn1_enc_length_cnt(trap->seqlen, &lenlen); 00353 tot_len += 1 + lenlen; 00354 00355 return tot_len; 00356 } 00357 00358 static void 00359 snmp_trap_varbind_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream, struct snmp_varbind *varbinds) 00360 { 00361 struct snmp_asn1_tlv tlv; 00362 struct snmp_varbind *varbind; 00363 00364 varbind = varbinds; 00365 00366 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->vbseqlen); 00367 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00368 00369 while (varbind != NULL) { 00370 snmp_append_outbound_varbind(pbuf_stream, varbind); 00371 00372 varbind = varbind->next; 00373 } 00374 } 00375 00376 /** 00377 * Encodes trap header from head to tail. 00378 */ 00379 static void 00380 snmp_trap_header_enc(struct snmp_msg_trap *trap, struct snmp_pbuf_stream *pbuf_stream) 00381 { 00382 struct snmp_asn1_tlv tlv; 00383 00384 /* 'Message' sequence */ 00385 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_SEQUENCE, 0, trap->seqlen); 00386 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00387 00388 /* version */ 00389 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 00390 snmp_asn1_enc_s32t_cnt(trap->snmp_version, &tlv.value_len); 00391 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00392 snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->snmp_version); 00393 00394 /* community */ 00395 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OCTET_STRING, 0, trap->comlen); 00396 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00397 snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)snmp_community_trap, trap->comlen); 00398 00399 /* 'PDU' sequence */ 00400 SNMP_ASN1_SET_TLV_PARAMS(tlv, (SNMP_ASN1_CLASS_CONTEXT | SNMP_ASN1_CONTENTTYPE_CONSTRUCTED | SNMP_ASN1_CONTEXT_PDU_TRAP), 0, trap->pdulen); 00401 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00402 00403 /* object ID */ 00404 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_OBJECT_ID, 0, 0); 00405 snmp_asn1_enc_oid_cnt(trap->enterprise->id, trap->enterprise->len, &tlv.value_len); 00406 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00407 snmp_asn1_enc_oid(pbuf_stream, trap->enterprise->id, trap->enterprise->len); 00408 00409 /* IP addr */ 00410 if (IP_IS_V6_VAL(trap->sip)) { 00411 #if LWIP_IPV6 00412 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip6(&trap->sip)->addr)); 00413 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00414 snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip6(&trap->sip)->addr, sizeof(ip_2_ip6(&trap->sip)->addr)); 00415 #endif 00416 } else { 00417 #if LWIP_IPV4 00418 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_IPADDR, 0, sizeof(ip_2_ip4(&trap->sip)->addr)); 00419 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00420 snmp_asn1_enc_raw(pbuf_stream, (const u8_t *)&ip_2_ip4(&trap->sip)->addr, sizeof(ip_2_ip4(&trap->sip)->addr)); 00421 #endif 00422 } 00423 00424 /* trap length */ 00425 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 00426 snmp_asn1_enc_s32t_cnt(trap->gen_trap, &tlv.value_len); 00427 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00428 snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->gen_trap); 00429 00430 /* specific trap */ 00431 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_INTEGER, 0, 0); 00432 snmp_asn1_enc_s32t_cnt(trap->spc_trap, &tlv.value_len); 00433 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00434 snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->spc_trap); 00435 00436 /* timestamp */ 00437 SNMP_ASN1_SET_TLV_PARAMS(tlv, SNMP_ASN1_TYPE_TIMETICKS, 0, 0); 00438 snmp_asn1_enc_s32t_cnt(trap->ts, &tlv.value_len); 00439 snmp_ans1_enc_tlv(pbuf_stream, &tlv); 00440 snmp_asn1_enc_s32t(pbuf_stream, tlv.value_len, trap->ts); 00441 } 00442 00443 #endif /* LWIP_SNMP */
Generated on Tue Jul 12 2022 13:15:54 by
