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