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 Bonjour by
msg_out.cpp
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_hton(&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 /** connect to the TRAP destination */ 00274 udp_connect(trap_msg.pcb, &trap_msg.dip, SNMP_TRAP_PORT); 00275 udp_send(trap_msg.pcb, p); 00276 /** disassociate remote address and port with this pcb */ 00277 udp_disconnect(trap_msg.pcb); 00278 00279 pbuf_free(p); 00280 } 00281 else 00282 { 00283 return ERR_MEM; 00284 } 00285 } 00286 } 00287 return ERR_OK; 00288 } 00289 00290 void 00291 snmp_coldstart_trap(void) 00292 { 00293 trap_msg.outvb.head = NULL; 00294 trap_msg.outvb.tail = NULL; 00295 trap_msg.outvb.count = 0; 00296 snmp_send_trap(SNMP_GENTRAP_COLDSTART, NULL, 0); 00297 } 00298 00299 void 00300 snmp_authfail_trap(void) 00301 { 00302 u8_t enable; 00303 snmp_get_snmpenableauthentraps(&enable); 00304 if (enable == 1) 00305 { 00306 trap_msg.outvb.head = NULL; 00307 trap_msg.outvb.tail = NULL; 00308 trap_msg.outvb.count = 0; 00309 snmp_send_trap(SNMP_GENTRAP_AUTHFAIL, NULL, 0); 00310 } 00311 } 00312 00313 /** 00314 * Sums response header field lengths from tail to head and 00315 * returns resp_header_lengths for second encoding pass. 00316 * 00317 * @param vb_len varbind-list length 00318 * @param rhl points to returned header lengths 00319 * @return the required lenght for encoding the response header 00320 */ 00321 static u16_t 00322 snmp_resp_header_sum(struct snmp_msg_pstat *m_stat, u16_t vb_len) 00323 { 00324 u16_t tot_len; 00325 struct snmp_resp_header_lengths *rhl; 00326 00327 rhl = &m_stat->rhl; 00328 tot_len = vb_len; 00329 snmp_asn1_enc_s32t_cnt(m_stat->error_index, &rhl->erridxlen); 00330 snmp_asn1_enc_length_cnt(rhl->erridxlen, &rhl->erridxlenlen); 00331 tot_len += 1 + rhl->erridxlenlen + rhl->erridxlen; 00332 00333 snmp_asn1_enc_s32t_cnt(m_stat->error_status, &rhl->errstatlen); 00334 snmp_asn1_enc_length_cnt(rhl->errstatlen, &rhl->errstatlenlen); 00335 tot_len += 1 + rhl->errstatlenlen + rhl->errstatlen; 00336 00337 snmp_asn1_enc_s32t_cnt(m_stat->rid, &rhl->ridlen); 00338 snmp_asn1_enc_length_cnt(rhl->ridlen, &rhl->ridlenlen); 00339 tot_len += 1 + rhl->ridlenlen + rhl->ridlen; 00340 00341 rhl->pdulen = tot_len; 00342 snmp_asn1_enc_length_cnt(rhl->pdulen, &rhl->pdulenlen); 00343 tot_len += 1 + rhl->pdulenlen; 00344 00345 rhl->comlen = m_stat->com_strlen; 00346 snmp_asn1_enc_length_cnt(rhl->comlen, &rhl->comlenlen); 00347 tot_len += 1 + rhl->comlenlen + rhl->comlen; 00348 00349 snmp_asn1_enc_s32t_cnt(snmp_version, &rhl->verlen); 00350 snmp_asn1_enc_length_cnt(rhl->verlen, &rhl->verlenlen); 00351 tot_len += 1 + rhl->verlen + rhl->verlenlen; 00352 00353 rhl->seqlen = tot_len; 00354 snmp_asn1_enc_length_cnt(rhl->seqlen, &rhl->seqlenlen); 00355 tot_len += 1 + rhl->seqlenlen; 00356 00357 return tot_len; 00358 } 00359 00360 /** 00361 * Sums trap header field lengths from tail to head and 00362 * returns trap_header_lengths for second encoding pass. 00363 * 00364 * @param vb_len varbind-list length 00365 * @param thl points to returned header lengths 00366 * @return the required lenght for encoding the trap header 00367 */ 00368 static u16_t 00369 snmp_trap_header_sum(struct snmp_msg_trap *m_trap, u16_t vb_len) 00370 { 00371 u16_t tot_len; 00372 struct snmp_trap_header_lengths *thl; 00373 00374 thl = &m_trap->thl; 00375 tot_len = vb_len; 00376 00377 snmp_asn1_enc_u32t_cnt(m_trap->ts, &thl->tslen); 00378 snmp_asn1_enc_length_cnt(thl->tslen, &thl->tslenlen); 00379 tot_len += 1 + thl->tslen + thl->tslenlen; 00380 00381 snmp_asn1_enc_s32t_cnt(m_trap->spc_trap, &thl->strplen); 00382 snmp_asn1_enc_length_cnt(thl->strplen, &thl->strplenlen); 00383 tot_len += 1 + thl->strplen + thl->strplenlen; 00384 00385 snmp_asn1_enc_s32t_cnt(m_trap->gen_trap, &thl->gtrplen); 00386 snmp_asn1_enc_length_cnt(thl->gtrplen, &thl->gtrplenlen); 00387 tot_len += 1 + thl->gtrplen + thl->gtrplenlen; 00388 00389 thl->aaddrlen = 4; 00390 snmp_asn1_enc_length_cnt(thl->aaddrlen, &thl->aaddrlenlen); 00391 tot_len += 1 + thl->aaddrlen + thl->aaddrlenlen; 00392 00393 snmp_asn1_enc_oid_cnt(m_trap->enterprise->len, &m_trap->enterprise->id[0], &thl->eidlen); 00394 snmp_asn1_enc_length_cnt(thl->eidlen, &thl->eidlenlen); 00395 tot_len += 1 + thl->eidlen + thl->eidlenlen; 00396 00397 thl->pdulen = tot_len; 00398 snmp_asn1_enc_length_cnt(thl->pdulen, &thl->pdulenlen); 00399 tot_len += 1 + thl->pdulenlen; 00400 00401 thl->comlen = sizeof(snmp_publiccommunity) - 1; 00402 snmp_asn1_enc_length_cnt(thl->comlen, &thl->comlenlen); 00403 tot_len += 1 + thl->comlenlen + thl->comlen; 00404 00405 snmp_asn1_enc_s32t_cnt(snmp_version, &thl->verlen); 00406 snmp_asn1_enc_length_cnt(thl->verlen, &thl->verlenlen); 00407 tot_len += 1 + thl->verlen + thl->verlenlen; 00408 00409 thl->seqlen = tot_len; 00410 snmp_asn1_enc_length_cnt(thl->seqlen, &thl->seqlenlen); 00411 tot_len += 1 + thl->seqlenlen; 00412 00413 return tot_len; 00414 } 00415 00416 /** 00417 * Sums varbind lengths from tail to head and 00418 * annotates lengths in varbind for second encoding pass. 00419 * 00420 * @param root points to the root of the variable binding list 00421 * @return the required lenght for encoding the variable bindings 00422 */ 00423 static u16_t 00424 snmp_varbind_list_sum(struct snmp_varbind_root *root) 00425 { 00426 struct snmp_varbind *vb; 00427 u32_t *uint_ptr; 00428 s32_t *sint_ptr; 00429 u16_t tot_len; 00430 00431 tot_len = 0; 00432 vb = root->tail; 00433 while ( vb != NULL ) 00434 { 00435 /* encoded value lenght depends on type */ 00436 switch (vb->value_type) 00437 { 00438 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): 00439 sint_ptr = (s32_t*)vb->value; 00440 snmp_asn1_enc_s32t_cnt(*sint_ptr, &vb->vlen); 00441 break; 00442 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): 00443 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): 00444 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): 00445 uint_ptr = (u32_t*)vb->value; 00446 snmp_asn1_enc_u32t_cnt(*uint_ptr, &vb->vlen); 00447 break; 00448 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): 00449 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): 00450 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): 00451 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): 00452 vb->vlen = vb->value_len; 00453 break; 00454 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): 00455 sint_ptr = (s32_t*)vb->value; 00456 snmp_asn1_enc_oid_cnt(vb->value_len / sizeof(s32_t), sint_ptr, &vb->vlen); 00457 break; 00458 default: 00459 /* unsupported type */ 00460 vb->vlen = 0; 00461 break; 00462 }; 00463 /* encoding length of value length field */ 00464 snmp_asn1_enc_length_cnt(vb->vlen, &vb->vlenlen); 00465 snmp_asn1_enc_oid_cnt(vb->ident_len, vb->ident, &vb->olen); 00466 snmp_asn1_enc_length_cnt(vb->olen, &vb->olenlen); 00467 00468 vb->seqlen = 1 + vb->vlenlen + vb->vlen; 00469 vb->seqlen += 1 + vb->olenlen + vb->olen; 00470 snmp_asn1_enc_length_cnt(vb->seqlen, &vb->seqlenlen); 00471 00472 /* varbind seq */ 00473 tot_len += 1 + vb->seqlenlen + vb->seqlen; 00474 00475 vb = vb->prev; 00476 } 00477 00478 /* varbind-list seq */ 00479 root->seqlen = tot_len; 00480 snmp_asn1_enc_length_cnt(root->seqlen, &root->seqlenlen); 00481 tot_len += 1 + root->seqlenlen; 00482 00483 return tot_len; 00484 } 00485 00486 /** 00487 * Encodes response header from head to tail. 00488 */ 00489 static u16_t 00490 snmp_resp_header_enc(struct snmp_msg_pstat *m_stat, struct pbuf *p) 00491 { 00492 u16_t ofs; 00493 00494 ofs = 0; 00495 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00496 ofs += 1; 00497 snmp_asn1_enc_length(p, ofs, m_stat->rhl.seqlen); 00498 ofs += m_stat->rhl.seqlenlen; 00499 00500 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00501 ofs += 1; 00502 snmp_asn1_enc_length(p, ofs, m_stat->rhl.verlen); 00503 ofs += m_stat->rhl.verlenlen; 00504 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.verlen, snmp_version); 00505 ofs += m_stat->rhl.verlen; 00506 00507 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); 00508 ofs += 1; 00509 snmp_asn1_enc_length(p, ofs, m_stat->rhl.comlen); 00510 ofs += m_stat->rhl.comlenlen; 00511 snmp_asn1_enc_raw(p, ofs, m_stat->rhl.comlen, m_stat->community); 00512 ofs += m_stat->rhl.comlen; 00513 00514 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP)); 00515 ofs += 1; 00516 snmp_asn1_enc_length(p, ofs, m_stat->rhl.pdulen); 00517 ofs += m_stat->rhl.pdulenlen; 00518 00519 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00520 ofs += 1; 00521 snmp_asn1_enc_length(p, ofs, m_stat->rhl.ridlen); 00522 ofs += m_stat->rhl.ridlenlen; 00523 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.ridlen, m_stat->rid); 00524 ofs += m_stat->rhl.ridlen; 00525 00526 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00527 ofs += 1; 00528 snmp_asn1_enc_length(p, ofs, m_stat->rhl.errstatlen); 00529 ofs += m_stat->rhl.errstatlenlen; 00530 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.errstatlen, m_stat->error_status); 00531 ofs += m_stat->rhl.errstatlen; 00532 00533 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00534 ofs += 1; 00535 snmp_asn1_enc_length(p, ofs, m_stat->rhl.erridxlen); 00536 ofs += m_stat->rhl.erridxlenlen; 00537 snmp_asn1_enc_s32t(p, ofs, m_stat->rhl.erridxlen, m_stat->error_index); 00538 ofs += m_stat->rhl.erridxlen; 00539 00540 return ofs; 00541 } 00542 00543 /** 00544 * Encodes trap header from head to tail. 00545 */ 00546 static u16_t 00547 snmp_trap_header_enc(struct snmp_msg_trap *m_trap, struct pbuf *p) 00548 { 00549 u16_t ofs; 00550 00551 ofs = 0; 00552 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00553 ofs += 1; 00554 snmp_asn1_enc_length(p, ofs, m_trap->thl.seqlen); 00555 ofs += m_trap->thl.seqlenlen; 00556 00557 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00558 ofs += 1; 00559 snmp_asn1_enc_length(p, ofs, m_trap->thl.verlen); 00560 ofs += m_trap->thl.verlenlen; 00561 snmp_asn1_enc_s32t(p, ofs, m_trap->thl.verlen, snmp_version); 00562 ofs += m_trap->thl.verlen; 00563 00564 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)); 00565 ofs += 1; 00566 snmp_asn1_enc_length(p, ofs, m_trap->thl.comlen); 00567 ofs += m_trap->thl.comlenlen; 00568 snmp_asn1_enc_raw(p, ofs, m_trap->thl.comlen, (u8_t *)&snmp_publiccommunity[0]); 00569 ofs += m_trap->thl.comlen; 00570 00571 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP)); 00572 ofs += 1; 00573 snmp_asn1_enc_length(p, ofs, m_trap->thl.pdulen); 00574 ofs += m_trap->thl.pdulenlen; 00575 00576 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); 00577 ofs += 1; 00578 snmp_asn1_enc_length(p, ofs, m_trap->thl.eidlen); 00579 ofs += m_trap->thl.eidlenlen; 00580 snmp_asn1_enc_oid(p, ofs, m_trap->enterprise->len, &m_trap->enterprise->id[0]); 00581 ofs += m_trap->thl.eidlen; 00582 00583 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR)); 00584 ofs += 1; 00585 snmp_asn1_enc_length(p, ofs, m_trap->thl.aaddrlen); 00586 ofs += m_trap->thl.aaddrlenlen; 00587 snmp_asn1_enc_raw(p, ofs, m_trap->thl.aaddrlen, &m_trap->sip_raw[0]); 00588 ofs += m_trap->thl.aaddrlen; 00589 00590 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00591 ofs += 1; 00592 snmp_asn1_enc_length(p, ofs, m_trap->thl.gtrplen); 00593 ofs += m_trap->thl.gtrplenlen; 00594 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.gtrplen, m_trap->gen_trap); 00595 ofs += m_trap->thl.gtrplen; 00596 00597 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)); 00598 ofs += 1; 00599 snmp_asn1_enc_length(p, ofs, m_trap->thl.strplen); 00600 ofs += m_trap->thl.strplenlen; 00601 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.strplen, m_trap->spc_trap); 00602 ofs += m_trap->thl.strplen; 00603 00604 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS)); 00605 ofs += 1; 00606 snmp_asn1_enc_length(p, ofs, m_trap->thl.tslen); 00607 ofs += m_trap->thl.tslenlen; 00608 snmp_asn1_enc_u32t(p, ofs, m_trap->thl.tslen, m_trap->ts); 00609 ofs += m_trap->thl.tslen; 00610 00611 return ofs; 00612 } 00613 00614 /** 00615 * Encodes varbind list from head to tail. 00616 */ 00617 static u16_t 00618 snmp_varbind_list_enc(struct snmp_varbind_root *root, struct pbuf *p, u16_t ofs) 00619 { 00620 struct snmp_varbind *vb; 00621 s32_t *sint_ptr; 00622 u32_t *uint_ptr; 00623 u8_t *raw_ptr; 00624 00625 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00626 ofs += 1; 00627 snmp_asn1_enc_length(p, ofs, root->seqlen); 00628 ofs += root->seqlenlen; 00629 00630 vb = root->head; 00631 while ( vb != NULL ) 00632 { 00633 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)); 00634 ofs += 1; 00635 snmp_asn1_enc_length(p, ofs, vb->seqlen); 00636 ofs += vb->seqlenlen; 00637 00638 snmp_asn1_enc_type(p, ofs, (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)); 00639 ofs += 1; 00640 snmp_asn1_enc_length(p, ofs, vb->olen); 00641 ofs += vb->olenlen; 00642 snmp_asn1_enc_oid(p, ofs, vb->ident_len, &vb->ident[0]); 00643 ofs += vb->olen; 00644 00645 snmp_asn1_enc_type(p, ofs, vb->value_type); 00646 ofs += 1; 00647 snmp_asn1_enc_length(p, ofs, vb->vlen); 00648 ofs += vb->vlenlen; 00649 00650 switch (vb->value_type) 00651 { 00652 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG): 00653 sint_ptr = (s32_t*)vb->value; 00654 snmp_asn1_enc_s32t(p, ofs, vb->vlen, *sint_ptr); 00655 break; 00656 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER): 00657 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE): 00658 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS): 00659 uint_ptr = (u32_t*)vb->value; 00660 snmp_asn1_enc_u32t(p, ofs, vb->vlen, *uint_ptr); 00661 break; 00662 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR): 00663 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR): 00664 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE): 00665 raw_ptr = (u8_t*)vb->value; 00666 snmp_asn1_enc_raw(p, ofs, vb->vlen, raw_ptr); 00667 break; 00668 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL): 00669 break; 00670 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID): 00671 sint_ptr = (s32_t*)vb->value; 00672 snmp_asn1_enc_oid(p, ofs, vb->value_len / sizeof(s32_t), sint_ptr); 00673 break; 00674 default: 00675 /* unsupported type */ 00676 break; 00677 }; 00678 ofs += vb->vlen; 00679 vb = vb->next; 00680 } 00681 return ofs; 00682 } 00683 00684 #endif /* LWIP_SNMP */
Generated on Tue Jul 12 2022 18:11:29 by
