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 F7_Ethernet by
msg_out.c
00001 /** 00002 * @file 00003 * SNMP output message processing (RFC1157). 00004 * 00005 * Output responses and traps are build in two passes: 00006 * 00007 * Pass 0: iterate over the output message backwards to determine encoding lengths 00008 * Pass 1: the actual forward encoding of internal form into ASN1 00009 * 00010 * The single-pass encoding method described by Comer & Stevens 00011 * requires extra buffer space and copying for reversal of the packet. 00012 * The buffer requirement can be prohibitively large for big payloads 00013 * (>= 484) therefore we use the two encoding passes. 00014 */ 00015 00016 /* 00017 * Copyright (c) 2006 Axon Digital Design B.V., The Netherlands. 00018 * All rights reserved. 00019 * 00020 * Redistribution and use in source and binary forms, with or without modification, 00021 * are permitted provided that the following conditions are met: 00022 * 00023 * 1. Redistributions of source code must retain the above copyright notice, 00024 * this list of conditions and the following disclaimer. 00025 * 2. Redistributions in binary form must reproduce the above copyright notice, 00026 * this list of conditions and the following disclaimer in the documentation 00027 * and/or other materials provided with the distribution. 00028 * 3. The name of the author may not be used to endorse or promote products 00029 * derived from this software without specific prior written permission. 00030 * 00031 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 00032 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00033 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00034 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00035 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00036 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00037 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00038 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 00039 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 00040 * OF SUCH DAMAGE. 00041 * 00042 * Author: Christiaan Simons <christiaan.simons@axon.tv> 00043 */ 00044 00045 #include "lwip/opt.h" 00046 00047 #if LWIP_SNMP /* don't build if not configured for use in lwipopts.h */ 00048 00049 #include "lwip/udp.h" 00050 #include "lwip/netif.h" 00051 #include "lwip/snmp.h" 00052 #include "lwip/snmp_asn1.h" 00053 #include "lwip/snmp_msg.h" 00054 00055 struct snmp_trap_dst 00056 { 00057 /* destination IP address in network order */ 00058 ip_addr_t dip; 00059 /* set to 0 when disabled, >0 when enabled */ 00060 u8_t enable; 00061 }; 00062 struct snmp_trap_dst trap_dst[SNMP_TRAP_DESTINATIONS]; 00063 00064 /** TRAP message structure */ 00065 struct snmp_msg_trap trap_msg; 00066 00067 static u16_t snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len); 00068 static u16_t snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len); 00069 static u16_t snmp_varbind_list_sum(struct snmp_varbind_root *root); 00070 00071 static u16_t snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p); 00072 static u16_t snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p); 00073 static u16_t snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs); 00074 00075 /** 00076 * Sets enable switch for this trap destination. 00077 * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 00078 * @param enable switch if 0 destination is disabled >0 enabled. 00079 */ 00080 void 00081 snmp_trap_dst_enable(u8_t dst_idx, u8_t enable) 00082 { 00083 if (dst_idx < SNMP_TRAP_DESTINATIONS) 00084 { 00085 trap_dst[dst_idx].enable = enable; 00086 } 00087 } 00088 00089 /** 00090 * Sets IPv4 address for this trap destination. 00091 * @param dst_idx index in 0 .. SNMP_TRAP_DESTINATIONS-1 00092 * @param dst IPv4 address in host order. 00093 */ 00094 void 00095 snmp_trap_dst_ip_set(u8_t dst_idx, ip_addr_t *dst) 00096 { 00097 if (dst_idx < SNMP_TRAP_DESTINATIONS) 00098 { 00099 ip_addr_set(&trap_dst[dst_idx].dip, dst); 00100 } 00101 } 00102 00103 /** 00104 * Sends a 'getresponse' message to the request originator. 00105 * 00106 * @param m_stat points to the current message request state source 00107 * @return ERR_OK when success, ERR_MEM if we're out of memory 00108 * 00109 * @note the caller is responsible for filling in outvb in the m_stat 00110 * and provide error-status and index (except for tooBig errors) ... 00111 */ 00112 err_t 00113 snmp_send_response(struct snmp_msg_pstat *m_stat) 00114 { 00115 struct snmp_varbind_root emptyvb = {NULL, NULL, 0, 0, 0}; 00116 struct pbuf *p; 00117 u16_t tot_len; 00118 err_t err; 00119 00120 /* pass 0, calculate length fields */ 00121 tot_len = snmp_varbind_list_sum(&m_stat->outvb); 00122 tot_len = snmp_resp_header_sum(m_stat, tot_len); 00123 00124 /* try allocating pbuf(s) for complete response */ 00125 p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); 00126 if (p == NULL) 00127 { 00128 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() tooBig\n")); 00129 00130 /* can't construct reply, return error-status tooBig */ 00131 m_stat->error_status = SNMP_ES_TOOBIG; 00132 m_stat->error_index = 0; 00133 /* pass 0, recalculate lengths, for empty varbind-list */ 00134 tot_len = snmp_varbind_list_sum(&emptyvb); 00135 tot_len = snmp_resp_header_sum(m_stat, tot_len); 00136 /* retry allocation once for header and empty varbind-list */ 00137 p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); 00138 } 00139 if (p != NULL) 00140 { 00141 /* first pbuf alloc try or retry alloc success */ 00142 u16_t ofs; 00143 00144 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() p != NULL\n")); 00145 00146 /* pass 1, size error, encode packet ino the pbuf(s) */ 00147 ofs = snmp_resp_header_enc(m_stat, p); 00148 snmp_varbind_list_enc(&m_stat->outvb, p, ofs); 00149 00150 switch (m_stat->error_status) 00151 { 00152 case SNMP_ES_TOOBIG: 00153 snmp_inc_snmpouttoobigs(); 00154 break; 00155 case SNMP_ES_NOSUCHNAME: 00156 snmp_inc_snmpoutnosuchnames(); 00157 break; 00158 case SNMP_ES_BADVALUE: 00159 snmp_inc_snmpoutbadvalues(); 00160 break; 00161 case SNMP_ES_GENERROR: 00162 snmp_inc_snmpoutgenerrs(); 00163 break; 00164 } 00165 snmp_inc_snmpoutgetresponses(); 00166 snmp_inc_snmpoutpkts(); 00167 00168 /** @todo do we need separate rx and tx pcbs for threaded case? */ 00169 /** connect to the originating source */ 00170 udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp); 00171 err = udp_send(m_stat->pcb, p); 00172 if (err == ERR_MEM) 00173 { 00174 /** @todo release some memory, retry and return tooBig? tooMuchHassle? */ 00175 err = ERR_MEM; 00176 } 00177 else 00178 { 00179 err = ERR_OK; 00180 } 00181 /** disassociate remote address and port with this pcb */ 00182 udp_disconnect(m_stat->pcb); 00183 00184 pbuf_free(p); 00185 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n")); 00186 return err; 00187 } 00188 else 00189 { 00190 /* first pbuf alloc try or retry alloc failed 00191 very low on memory, couldn't return tooBig */ 00192 return ERR_MEM; 00193 } 00194 } 00195 00196 00197 /** 00198 * Sends an generic or enterprise specific trap message. 00199 * 00200 * @param generic_trap is the trap code 00201 * @param eoid points to enterprise object identifier 00202 * @param specific_trap used for enterprise traps when generic_trap == 6 00203 * @return ERR_OK when success, ERR_MEM if we're out of memory 00204 * 00205 * @note the caller is responsible for filling in outvb in the trap_msg 00206 * @note the use of the enterpise identifier field 00207 * is per RFC1215. 00208 * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps 00209 * and .iso.org.dod.internet.private.enterprises.yourenterprise 00210 * (sysObjectID) for specific traps. 00211 */ 00212 err_t 00213 snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap) 00214 { 00215 struct snmp_trap_dst *td; 00216 struct netif *dst_if; 00217 ip_addr_t dst_ip; 00218 struct pbuf *p; 00219 u16_t i,tot_len; 00220 00221 for (i=0, td = &trap_dst[0]; i<SNMP_TRAP_DESTINATIONS; i++, td++) 00222 { 00223 if ((td->enable != 0) && !ip_addr_isany(&td->dip)) 00224 { 00225 /* network order trap destination */ 00226 ip_addr_copy(trap_msg.dip, td->dip); 00227 /* lookup current source address for this dst */ 00228 dst_if = ip_route(&td->dip); 00229 ip_addr_copy(dst_ip, dst_if->ip_addr); 00230 /* @todo: what about IPv6? */ 00231 trap_msg.sip_raw[0] = ip4_addr1(&dst_ip); 00232 trap_msg.sip_raw[1] = ip4_addr2(&dst_ip); 00233 trap_msg.sip_raw[2] = ip4_addr3(&dst_ip); 00234 trap_msg.sip_raw[3] = ip4_addr4(&dst_ip); 00235 trap_msg.gen_trap = generic_trap; 00236 trap_msg.spc_trap = specific_trap; 00237 if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) 00238 { 00239 /* enterprise-Specific trap */ 00240 trap_msg.enterprise = eoid; 00241 } 00242 else 00243 { 00244 /* generic (MIB-II) trap */ 00245 snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); 00246 } 00247 snmp_get_sysuptime(&trap_msg.ts); 00248 00249 /* pass 0, calculate length fields */ 00250 tot_len = snmp_varbind_list_sum(&trap_msg.outvb); 00251 tot_len = snmp_trap_header_sum(&trap_msg, tot_len); 00252 00253 /* allocate pbuf(s) */ 00254 p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); 00255 if (p != NULL) 00256 { 00257 u16_t ofs; 00258 00259 /* pass 1, encode packet ino the pbuf(s) */ 00260 ofs = snmp_trap_header_enc(&trap_msg, p); 00261 snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); 00262 00263 snmp_inc_snmpouttraps(); 00264 snmp_inc_snmpoutpkts(); 00265 00266 /** send to the TRAP destination */ 00267 udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT); 00268 00269 pbuf_free(p); 00270 } 00271 else 00272 { 00273 return ERR_MEM; 00274 } 00275 } 00276 } 00277 return ERR_OK; 00278 } 00279 00280 void 00281 snmp_coldstart_trap(void) 00282 { 00283 trap_msg.outvb.head = NULL; 00284 trap_msg.outvb.tail = NULL; 00285 trap_msg.outvb.count = 0; 00286 snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); 00287 } 00288 00289 void 00290 snmp_authfail_trap(void) 00291 { 00292 u8_t enable; 00293 snmp_get_snmpenableauthentraps(&enable); 00294 if (enable == 1) 00295 { 00296 trap_msg.outvb.head = NULL; 00297 trap_msg.outvb.tail = NULL; 00298 trap_msg.outvb.count = 0; 00299 snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); 00300 } 00301 } 00302 00303 /** 00304 * Sums response header field lengths from tail to head and 00305 * returns resp_header_lengths for second encoding pass. 00306 * 00307 * @param vb_len varbind-list length 00308 * @param rhl points to returned header lengths 00309 * @return the required lenght for encoding the response header 00310 */ 00311 static u16_t 00312 snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) 00313 { 00314 u16_t tot_len; 00315 struct snmp_resp_header_lengths *rhl; 00316 00317 rhl = &m_stat->rhl; 00318 tot_len = vb_len; 00319 snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); 00320 snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); 00321 tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; 00322 00323 snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); 00324 snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); 00325 tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; 00326 00327 snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); 00328 snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); 00329 tot_len += 1 + rhl->ridlenlen + rhl->ridlen; 00330 00331 rhl->pdulen = tot_len; 00332 snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); 00333 tot_len += 1 + rhl->pdulenlen; 00334 00335 rhl->comlen = m_stat->com_strlen; 00336 snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); 00337 tot_len += 1 + rhl->comlenlen + rhl->comlen; 00338 00339 snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); 00340 snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); 00341 tot_len += 1 + rhl->verlen + rhl->verlenlen; 00342 00343 rhl->seqlen = tot_len; 00344 snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); 00345 tot_len += 1 + rhl->seqlenlen; 00346 00347 return tot_len; 00348 } 00349 00350 /** 00351 * Sums trap header field lengths from tail to head and 00352 * returns trap_header_lengths for second encoding pass. 00353 * 00354 * @param vb_len varbind-list length 00355 * @param thl points to returned header lengths 00356 * @return the required lenght for encoding the trap header 00357 */ 00358 static u16_t 00359 snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) 00360 { 00361 u16_t tot_len; 00362 struct snmp_trap_header_lengths *thl; 00363 00364 thl = &m_trap->thl; 00365 tot_len = vb_len; 00366 00367 snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); 00368 snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); 00369 tot_len += 1 + thl->tslen + thl->tslenlen; 00370 00371 snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); 00372 snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); 00373 tot_len += 1 + thl->strplen + thl->strplenlen; 00374 00375 snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); 00376 snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); 00377 tot_len += 1 + thl->gtrplen + thl->gtrplenlen; 00378 00379 thl->aaddrlen = 4; 00380 snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); 00381 tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; 00382 00383 snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); 00384 snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); 00385 tot_len += 1 + thl->eidlen + thl->eidlenlen; 00386 00387 thl->pdulen = tot_len; 00388 snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); 00389 tot_len += 1 + thl->pdulenlen; 00390 00391 thl->comlen = sizeof(snmp_publiccommunity) - 1; 00392 snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); 00393 tot_len += 1 + thl->comlenlen + thl->comlen; 00394 00395 snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); 00396 snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); 00397 tot_len += 1 + thl->verlen + thl->verlenlen; 00398 00399 thl->seqlen = tot_len; 00400 snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); 00401 tot_len += 1 + thl->seqlenlen; 00402 00403 return tot_len; 00404 } 00405 00406 /** 00407 * Sums varbind lengths from tail to head and 00408 * annotates lengths in varbind for second encoding pass. 00409 * 00410 * @param root points to the root of the variable binding list 00411 * @return the required lenght for encoding the variable bindings 00412 */ 00413 static u16_t 00414 snmp_varbind_list_sum(struct snmp_varbind_root *root) 00415 { 00416 struct snmp_varbind *vb; 00417 u32_t *uint_ptr; 00418 s32_t *sint_ptr; 00419 u16_t tot_len; 00420 00421 tot_len = 0; 00422 vb = root->tail; 00423 while ( vb != NULL ) 00424 { 00425 /* encoded value lenght depends on type */ 00426 switch (vb->value_type) 00427 { 00428 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): 00429 sint_ptr = (s32_t*)vb->value; 00430 snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); 00431 break; 00432 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): 00433 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): 00434 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): 00435 uint_ptr = (u32_t*)vb->value; 00436 snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); 00437 break; 00438 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): 00439 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): 00440 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): 00441 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): 00442 vb->vlen = vb->value_len; 00443 break; 00444 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): 00445 sint_ptr = (s32_t*)vb->value; 00446 snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); 00447 break; 00448 default: 00449 /* unsupported type */ 00450 vb->vlen = 0; 00451 break; 00452 }; 00453 /* encoding length of value length field */ 00454 snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); 00455 snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); 00456 snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); 00457 00458 vb->seqlen = 1 + vb->vlenlen + vb->vlen; 00459 vb->seqlen += 1 + vb->olenlen + vb->olen; 00460 snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); 00461 00462 /* varbind seq */ 00463 tot_len += 1 + vb->seqlenlen + vb->seqlen; 00464 00465 vb = vb->prev; 00466 } 00467 00468 /* varbind-list seq */ 00469 root->seqlen = tot_len; 00470 snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); 00471 tot_len += 1 + root->seqlenlen; 00472 00473 return tot_len; 00474 } 00475 00476 /** 00477 * Encodes response header from head to tail. 00478 */ 00479 static u16_t 00480 snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) 00481 { 00482 u16_t ofs; 00483 00484 ofs = 0; 00485 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00486 ofs += 1; 00487 snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); 00488 ofs += m_stat->rhl.seqlenlen; 00489 00490 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00491 ofs += 1; 00492 snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); 00493 ofs += m_stat->rhl.verlenlen; 00494 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); 00495 ofs += m_stat->rhl.verlen; 00496 00497 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); 00498 ofs += 1; 00499 snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); 00500 ofs += m_stat->rhl.comlenlen; 00501 snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); 00502 ofs += m_stat->rhl.comlen; 00503 00504 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); 00505 ofs += 1; 00506 snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); 00507 ofs += m_stat->rhl.pdulenlen; 00508 00509 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00510 ofs += 1; 00511 snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen); 00512 ofs += m_stat->rhl.ridlenlen; 00513 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); 00514 ofs += m_stat->rhl.ridlen; 00515 00516 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00517 ofs += 1; 00518 snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen); 00519 ofs += m_stat->rhl.errstatlenlen; 00520 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); 00521 ofs += m_stat->rhl.errstatlen; 00522 00523 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00524 ofs += 1; 00525 snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); 00526 ofs += m_stat->rhl.erridxlenlen; 00527 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); 00528 ofs += m_stat->rhl.erridxlen; 00529 00530 return ofs; 00531 } 00532 00533 /** 00534 * Encodes trap header from head to tail. 00535 */ 00536 static u16_t 00537 snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) 00538 { 00539 u16_t ofs; 00540 00541 ofs = 0; 00542 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00543 ofs += 1; 00544 snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); 00545 ofs += m_trap->thl.seqlenlen; 00546 00547 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00548 ofs += 1; 00549 snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); 00550 ofs += m_trap->thl.verlenlen; 00551 snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); 00552 ofs += m_trap->thl.verlen; 00553 00554 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); 00555 ofs += 1; 00556 snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); 00557 ofs += m_trap->thl.comlenlen; 00558 snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); 00559 ofs += m_trap->thl.comlen; 00560 00561 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); 00562 ofs += 1; 00563 snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); 00564 ofs += m_trap->thl.pdulenlen; 00565 00566 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); 00567 ofs += 1; 00568 snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); 00569 ofs += m_trap->thl.eidlenlen; 00570 snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); 00571 ofs += m_trap->thl.eidlen; 00572 00573 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); 00574 ofs += 1; 00575 snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); 00576 ofs += m_trap->thl.aaddrlenlen; 00577 snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); 00578 ofs += m_trap->thl.aaddrlen; 00579 00580 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00581 ofs += 1; 00582 snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen); 00583 ofs += m_trap->thl.gtrplenlen; 00584 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); 00585 ofs += m_trap->thl.gtrplen; 00586 00587 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00588 ofs += 1; 00589 snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); 00590 ofs += m_trap->thl.strplenlen; 00591 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); 00592 ofs += m_trap->thl.strplen; 00593 00594 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); 00595 ofs += 1; 00596 snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); 00597 ofs += m_trap->thl.tslenlen; 00598 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); 00599 ofs += m_trap->thl.tslen; 00600 00601 return ofs; 00602 } 00603 00604 /** 00605 * Encodes varbind list from head to tail. 00606 */ 00607 static u16_t 00608 snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) 00609 { 00610 struct snmp_varbind *vb; 00611 s32_t *sint_ptr; 00612 u32_t *uint_ptr; 00613 u8_t *raw_ptr; 00614 00615 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00616 ofs += 1; 00617 snmp_asn1_enc_length(p, ofs, root->seqlen); 00618 ofs += root->seqlenlen; 00619 00620 vb = root->head; 00621 while ( vb != NULL ) 00622 { 00623 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00624 ofs += 1; 00625 snmp_asn1_enc_length(p, ofs, vb->seqlen); 00626 ofs += vb->seqlenlen; 00627 00628 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); 00629 ofs += 1; 00630 snmp_asn1_enc_length(p, ofs, vb->olen); 00631 ofs += vb->olenlen; 00632 snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); 00633 ofs += vb->olen; 00634 00635 snmp_asn1_enc_type(p, ofs, vb->value_type); 00636 ofs += 1; 00637 snmp_asn1_enc_length(p, ofs, vb->vlen); 00638 ofs += vb->vlenlen; 00639 00640 switch (vb->value_type) 00641 { 00642 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): 00643 sint_ptr = (s32_t*)vb->value; 00644 snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); 00645 break; 00646 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): 00647 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): 00648 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): 00649 uint_ptr = (u32_t*)vb->value; 00650 snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); 00651 break; 00652 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): 00653 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): 00654 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): 00655 raw_ptr = (u8_t*)vb->value; 00656 snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); 00657 break; 00658 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): 00659 break; 00660 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): 00661 sint_ptr = (s32_t*)vb->value; 00662 snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); 00663 break; 00664 default: 00665 /* unsupported type */ 00666 break; 00667 }; 00668 ofs += vb->vlen; 00669 vb = vb->next; 00670 } 00671 return ofs; 00672 } 00673 00674 #endif /* LWIP_SNMP */
Generated on Wed Jul 13 2022 02:45:41 by
1.7.2
