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 lwip 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 if (m_stat->error_status == SNMP_ES_TOOBIG) 00149 { 00150 snmp_varbind_list_enc(&emptyvb, p, ofs); 00151 } 00152 else 00153 { 00154 snmp_varbind_list_enc(&m_stat->outvb, p, ofs); 00155 } 00156 00157 switch (m_stat->error_status) 00158 { 00159 case SNMP_ES_TOOBIG: 00160 snmp_inc_snmpouttoobigs(); 00161 break; 00162 case SNMP_ES_NOSUCHNAME: 00163 snmp_inc_snmpoutnosuchnames(); 00164 break; 00165 case SNMP_ES_BADVALUE: 00166 snmp_inc_snmpoutbadvalues(); 00167 break; 00168 case SNMP_ES_GENERROR: 00169 snmp_inc_snmpoutgenerrs(); 00170 break; 00171 } 00172 snmp_inc_snmpoutgetresponses(); 00173 snmp_inc_snmpoutpkts(); 00174 00175 /** @todo do we need separate rx and tx pcbs for threaded case? */ 00176 /** connect to the originating source */ 00177 udp_connect(m_stat->pcb, &m_stat->sip, m_stat->sp); 00178 err = udp_send(m_stat->pcb, p); 00179 if (err == ERR_MEM) 00180 { 00181 /** @todo release some memory, retry and return tooBig? tooMuchHassle? */ 00182 err = ERR_MEM; 00183 } 00184 else 00185 { 00186 err = ERR_OK; 00187 } 00188 /** disassociate remote address and port with this pcb */ 00189 udp_disconnect(m_stat->pcb); 00190 00191 pbuf_free(p); 00192 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_snd_response() done\n")); 00193 return err; 00194 } 00195 else 00196 { 00197 /* first pbuf alloc try or retry alloc failed 00198 very low on memory, couldn't return tooBig */ 00199 return ERR_MEM; 00200 } 00201 } 00202 00203 00204 /** 00205 * Sends an generic or enterprise specific trap message. 00206 * 00207 * @param generic_trap is the trap code 00208 * @param eoid points to enterprise object identifier 00209 * @param specific_trap used for enterprise traps when generic_trap == 6 00210 * @return ERR_OK when success, ERR_MEM if we're out of memory 00211 * 00212 * @note the caller is responsible for filling in outvb in the trap_msg 00213 * @note the use of the enterpise identifier field 00214 * is per RFC1215. 00215 * Use .iso.org.dod.internet.mgmt.mib-2.snmp for generic traps 00216 * and .iso.org.dod.internet.private.enterprises.yourenterprise 00217 * (sysObjectID) for specific traps. 00218 */ 00219 err_t 00220 snmp_send_trap(s8_t generic_trap, struct snmp_obj_id *eoid, s32_t specific_trap) 00221 { 00222 struct snmp_trap_dst *td; 00223 struct netif *dst_if; 00224 ip_addr_t dst_ip; 00225 struct pbuf *p; 00226 u16_t i,tot_len; 00227 00228 for (i=0, td = &trap_dst[0]; i<SNMP_TRAP_DESTINATIONS; i++, td++) 00229 { 00230 if ((td->enable != 0) && !ip_addr_isany(&td->dip)) 00231 { 00232 /* network order trap destination */ 00233 ip_addr_copy(trap_msg.dip, td->dip); 00234 /* lookup current source address for this dst */ 00235 dst_if = ip_route(&td->dip); 00236 ip_addr_copy(dst_ip, dst_if->ip_addr); 00237 /* @todo: what about IPv6? */ 00238 trap_msg.sip_raw[0] = ip4_addr1(&dst_ip); 00239 trap_msg.sip_raw[1] = ip4_addr2(&dst_ip); 00240 trap_msg.sip_raw[2] = ip4_addr3(&dst_ip); 00241 trap_msg.sip_raw[3] = ip4_addr4(&dst_ip); 00242 trap_msg.gen_trap = generic_trap; 00243 trap_msg.spc_trap = specific_trap; 00244 if (generic_trap == SNMP_GENTRAP_ENTERPRISESPC) 00245 { 00246 /* enterprise-Specific trap */ 00247 trap_msg.enterprise = eoid; 00248 } 00249 else 00250 { 00251 /* generic (MIB-II) trap */ 00252 snmp_get_snmpgrpid_ptr(&trap_msg.enterprise); 00253 } 00254 snmp_get_sysuptime(&trap_msg.ts); 00255 00256 /* pass 0, calculate length fields */ 00257 tot_len = snmp_varbind_list_sum(&trap_msg.outvb); 00258 tot_len = snmp_trap_header_sum(&trap_msg, tot_len); 00259 00260 /* allocate pbuf(s) */ 00261 p = pbuf_alloc(PBUF_TRANSPORT, tot_len, PBUF_POOL); 00262 if (p != NULL) 00263 { 00264 u16_t ofs; 00265 00266 /* pass 1, encode packet ino the pbuf(s) */ 00267 ofs = snmp_trap_header_enc(&trap_msg, p); 00268 snmp_varbind_list_enc(&trap_msg.outvb, p, ofs); 00269 00270 snmp_inc_snmpouttraps(); 00271 snmp_inc_snmpoutpkts(); 00272 00273 /** send to the TRAP destination */ 00274 udp_sendto(trap_msg.pcb, p, &trap_msg.dip, SNMP_TRAP_PORT); 00275 00276 pbuf_free(p); 00277 } 00278 else 00279 { 00280 return ERR_MEM; 00281 } 00282 } 00283 } 00284 return ERR_OK; 00285 } 00286 00287 void 00288 snmp_coldstart_trap(void) 00289 { 00290 trap_msg.outvb.head = NULL; 00291 trap_msg.outvb.tail = NULL; 00292 trap_msg.outvb.count = 0; 00293 snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); 00294 } 00295 00296 void 00297 snmp_authfail_trap(void) 00298 { 00299 u8_t enable; 00300 snmp_get_snmpenableauthentraps(&enable); 00301 if (enable == 1) 00302 { 00303 trap_msg.outvb.head = NULL; 00304 trap_msg.outvb.tail = NULL; 00305 trap_msg.outvb.count = 0; 00306 snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); 00307 } 00308 } 00309 00310 /** 00311 * Sums response header field lengths from tail to head and 00312 * returns resp_header_lengths for second encoding pass. 00313 * 00314 * @param vb_len varbind-list length 00315 * @param rhl points to returned header lengths 00316 * @return the required lenght for encoding the response header 00317 */ 00318 static u16_t 00319 snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) 00320 { 00321 u16_t tot_len; 00322 struct snmp_resp_header_lengths *rhl; 00323 00324 rhl = &m_stat->rhl; 00325 tot_len = vb_len; 00326 snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); 00327 snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); 00328 tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; 00329 00330 snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); 00331 snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); 00332 tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; 00333 00334 snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); 00335 snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); 00336 tot_len += 1 + rhl->ridlenlen + rhl->ridlen; 00337 00338 rhl->pdulen = tot_len; 00339 snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); 00340 tot_len += 1 + rhl->pdulenlen; 00341 00342 rhl->comlen = m_stat->com_strlen; 00343 snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); 00344 tot_len += 1 + rhl->comlenlen + rhl->comlen; 00345 00346 snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); 00347 snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); 00348 tot_len += 1 + rhl->verlen + rhl->verlenlen; 00349 00350 rhl->seqlen = tot_len; 00351 snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); 00352 tot_len += 1 + rhl->seqlenlen; 00353 00354 return tot_len; 00355 } 00356 00357 /** 00358 * Sums trap header field lengths from tail to head and 00359 * returns trap_header_lengths for second encoding pass. 00360 * 00361 * @param vb_len varbind-list length 00362 * @param thl points to returned header lengths 00363 * @return the required lenght for encoding the trap header 00364 */ 00365 static u16_t 00366 snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) 00367 { 00368 u16_t tot_len; 00369 struct snmp_trap_header_lengths *thl; 00370 00371 thl = &m_trap->thl; 00372 tot_len = vb_len; 00373 00374 snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); 00375 snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); 00376 tot_len += 1 + thl->tslen + thl->tslenlen; 00377 00378 snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); 00379 snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); 00380 tot_len += 1 + thl->strplen + thl->strplenlen; 00381 00382 snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); 00383 snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); 00384 tot_len += 1 + thl->gtrplen + thl->gtrplenlen; 00385 00386 thl->aaddrlen = 4; 00387 snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); 00388 tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; 00389 00390 snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); 00391 snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); 00392 tot_len += 1 + thl->eidlen + thl->eidlenlen; 00393 00394 thl->pdulen = tot_len; 00395 snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); 00396 tot_len += 1 + thl->pdulenlen; 00397 00398 thl->comlen = sizeof(snmp_publiccommunity) - 1; 00399 snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); 00400 tot_len += 1 + thl->comlenlen + thl->comlen; 00401 00402 snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); 00403 snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); 00404 tot_len += 1 + thl->verlen + thl->verlenlen; 00405 00406 thl->seqlen = tot_len; 00407 snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); 00408 tot_len += 1 + thl->seqlenlen; 00409 00410 return tot_len; 00411 } 00412 00413 /** 00414 * Sums varbind lengths from tail to head and 00415 * annotates lengths in varbind for second encoding pass. 00416 * 00417 * @param root points to the root of the variable binding list 00418 * @return the required lenght for encoding the variable bindings 00419 */ 00420 static u16_t 00421 snmp_varbind_list_sum(struct snmp_varbind_root *root) 00422 { 00423 struct snmp_varbind *vb; 00424 u32_t *uint_ptr; 00425 s32_t *sint_ptr; 00426 u16_t tot_len; 00427 00428 tot_len = 0; 00429 vb = root->tail; 00430 while ( vb != NULL ) 00431 { 00432 /* encoded value lenght depends on type */ 00433 switch (vb->value_type) 00434 { 00435 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): 00436 sint_ptr = (s32_t*)vb->value; 00437 snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); 00438 break; 00439 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): 00440 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): 00441 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): 00442 uint_ptr = (u32_t*)vb->value; 00443 snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); 00444 break; 00445 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): 00446 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): 00447 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): 00448 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): 00449 vb->vlen = vb->value_len; 00450 break; 00451 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): 00452 sint_ptr = (s32_t*)vb->value; 00453 snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); 00454 break; 00455 default: 00456 /* unsupported type */ 00457 vb->vlen = 0; 00458 break; 00459 }; 00460 /* encoding length of value length field */ 00461 snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); 00462 snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); 00463 snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); 00464 00465 vb->seqlen = 1 + vb->vlenlen + vb->vlen; 00466 vb->seqlen += 1 + vb->olenlen + vb->olen; 00467 snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); 00468 00469 /* varbind seq */ 00470 tot_len += 1 + vb->seqlenlen + vb->seqlen; 00471 00472 vb = vb->prev; 00473 } 00474 00475 /* varbind-list seq */ 00476 root->seqlen = tot_len; 00477 snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); 00478 tot_len += 1 + root->seqlenlen; 00479 00480 return tot_len; 00481 } 00482 00483 /** 00484 * Encodes response header from head to tail. 00485 */ 00486 static u16_t 00487 snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) 00488 { 00489 u16_t ofs; 00490 00491 ofs = 0; 00492 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00493 ofs += 1; 00494 snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); 00495 ofs += m_stat->rhl.seqlenlen; 00496 00497 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00498 ofs += 1; 00499 snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); 00500 ofs += m_stat->rhl.verlenlen; 00501 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); 00502 ofs += m_stat->rhl.verlen; 00503 00504 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); 00505 ofs += 1; 00506 snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); 00507 ofs += m_stat->rhl.comlenlen; 00508 snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); 00509 ofs += m_stat->rhl.comlen; 00510 00511 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); 00512 ofs += 1; 00513 snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); 00514 ofs += m_stat->rhl.pdulenlen; 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.ridlen); 00519 ofs += m_stat->rhl.ridlenlen; 00520 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); 00521 ofs += m_stat->rhl.ridlen; 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.errstatlen); 00526 ofs += m_stat->rhl.errstatlenlen; 00527 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); 00528 ofs += m_stat->rhl.errstatlen; 00529 00530 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00531 ofs += 1; 00532 snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); 00533 ofs += m_stat->rhl.erridxlenlen; 00534 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); 00535 ofs += m_stat->rhl.erridxlen; 00536 00537 return ofs; 00538 } 00539 00540 /** 00541 * Encodes trap header from head to tail. 00542 */ 00543 static u16_t 00544 snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) 00545 { 00546 u16_t ofs; 00547 00548 ofs = 0; 00549 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00550 ofs += 1; 00551 snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); 00552 ofs += m_trap->thl.seqlenlen; 00553 00554 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00555 ofs += 1; 00556 snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); 00557 ofs += m_trap->thl.verlenlen; 00558 snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); 00559 ofs += m_trap->thl.verlen; 00560 00561 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); 00562 ofs += 1; 00563 snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); 00564 ofs += m_trap->thl.comlenlen; 00565 snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); 00566 ofs += m_trap->thl.comlen; 00567 00568 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); 00569 ofs += 1; 00570 snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); 00571 ofs += m_trap->thl.pdulenlen; 00572 00573 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); 00574 ofs += 1; 00575 snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); 00576 ofs += m_trap->thl.eidlenlen; 00577 snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); 00578 ofs += m_trap->thl.eidlen; 00579 00580 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); 00581 ofs += 1; 00582 snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); 00583 ofs += m_trap->thl.aaddrlenlen; 00584 snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); 00585 ofs += m_trap->thl.aaddrlen; 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.gtrplen); 00590 ofs += m_trap->thl.gtrplenlen; 00591 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); 00592 ofs += m_trap->thl.gtrplen; 00593 00594 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00595 ofs += 1; 00596 snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); 00597 ofs += m_trap->thl.strplenlen; 00598 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); 00599 ofs += m_trap->thl.strplen; 00600 00601 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); 00602 ofs += 1; 00603 snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); 00604 ofs += m_trap->thl.tslenlen; 00605 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); 00606 ofs += m_trap->thl.tslen; 00607 00608 return ofs; 00609 } 00610 00611 /** 00612 * Encodes varbind list from head to tail. 00613 */ 00614 static u16_t 00615 snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) 00616 { 00617 struct snmp_varbind *vb; 00618 s32_t *sint_ptr; 00619 u32_t *uint_ptr; 00620 u8_t *raw_ptr; 00621 00622 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00623 ofs += 1; 00624 snmp_asn1_enc_length(p, ofs, root->seqlen); 00625 ofs += root->seqlenlen; 00626 00627 vb = root->head; 00628 while ( vb != NULL ) 00629 { 00630 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00631 ofs += 1; 00632 snmp_asn1_enc_length(p, ofs, vb->seqlen); 00633 ofs += vb->seqlenlen; 00634 00635 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); 00636 ofs += 1; 00637 snmp_asn1_enc_length(p, ofs, vb->olen); 00638 ofs += vb->olenlen; 00639 snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); 00640 ofs += vb->olen; 00641 00642 snmp_asn1_enc_type(p, ofs, vb->value_type); 00643 ofs += 1; 00644 snmp_asn1_enc_length(p, ofs, vb->vlen); 00645 ofs += vb->vlenlen; 00646 00647 switch (vb->value_type) 00648 { 00649 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): 00650 sint_ptr = (s32_t*)vb->value; 00651 snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); 00652 break; 00653 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): 00654 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): 00655 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): 00656 uint_ptr = (u32_t*)vb->value; 00657 snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); 00658 break; 00659 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): 00660 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): 00661 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): 00662 raw_ptr = (u8_t*)vb->value; 00663 snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); 00664 break; 00665 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): 00666 break; 00667 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): 00668 sint_ptr = (s32_t*)vb->value; 00669 snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); 00670 break; 00671 default: 00672 /* unsupported type */ 00673 break; 00674 }; 00675 ofs += vb->vlen; 00676 vb = vb->next; 00677 } 00678 return ofs; 00679 } 00680 00681 #endif /* LWIP_SNMP */
Generated on Tue Jul 12 2022 11:29:37 by
