00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "lwip/opt.h"
00036
00037 #if LWIP_SNMP
00038
00039 #include "lwip/snmp.h"
00040 #include "lwip/snmp_asn1.h"
00041 #include "lwip/snmp_msg.h"
00042 #include "lwip/snmp_structs.h"
00043 #include "lwip/ip_addr.h"
00044 #include "lwip/memp.h"
00045 #include "lwip/udp.h"
00046 #include "lwip/stats.h"
00047
00048 #include <string.h>
00049
00050
00051
00052 const s32_t snmp_version = 0;
00053
00054 const char snmp_publiccommunity[7] = "public";
00055
00056
00057 struct snmp_msg_pstat msg_input_list[SNMP_CONCURRENT_REQUESTS];
00058
00059 struct udp_pcb *snmp1_pcb;
00060
00061 static void snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port);
00062 static err_t snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
00063 static err_t snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat);
00064
00065
00066
00067
00068
00069
00070 void
00071 snmp_init(void)
00072 {
00073 struct snmp_msg_pstat *msg_ps;
00074 u8_t i;
00075
00076 snmp1_pcb = udp_new();
00077 if (snmp1_pcb != NULL)
00078 {
00079 udp_recv(snmp1_pcb, snmp_recv, (void *)SNMP_IN_PORT);
00080 udp_bind(snmp1_pcb, IP_ADDR_ANY, SNMP_IN_PORT);
00081 }
00082 msg_ps = &msg_input_list[0];
00083 for (i=0; i<SNMP_CONCURRENT_REQUESTS; i++)
00084 {
00085 msg_ps->state = SNMP_MSG_EMPTY;
00086 msg_ps->error_index = 0;
00087 msg_ps->error_status = SNMP_ES_NOERROR;
00088 msg_ps++;
00089 }
00090 trap_msg.pcb = snmp1_pcb;
00091
00092 #ifdef SNMP_PRIVATE_MIB_INIT
00093
00094
00095
00096
00097 SNMP_PRIVATE_MIB_INIT();
00098 #endif
00099
00100
00101
00102 snmp_coldstart_trap();
00103 }
00104
00105 static void
00106 snmp_error_response(struct snmp_msg_pstat *msg_ps, u8_t error)
00107 {
00108
00109 int v;
00110 struct snmp_varbind *vbi = msg_ps->invb.head;
00111 struct snmp_varbind *vbo = msg_ps->outvb.head;
00112 for (v=0; v<msg_ps->vb_idx; v++) {
00113 vbi->ident_len = vbo->ident_len;
00114 vbo->ident_len = 0;
00115 vbi->ident = vbo->ident;
00116 vbo->ident = NULL;
00117 vbi = vbi->next;
00118 vbo = vbo->next;
00119 }
00120
00121 snmp_varbind_list_free(&msg_ps->outvb);
00122
00123 msg_ps->outvb = msg_ps->invb;
00124 msg_ps->invb.head = NULL;
00125 msg_ps->invb.tail = NULL;
00126 msg_ps->invb.count = 0;
00127 msg_ps->error_status = error;
00128
00129 msg_ps->error_index = (error != SNMP_ES_TOOBIG) ? (1 + msg_ps->vb_idx) : 0;
00130 snmp_send_response(msg_ps);
00131 snmp_varbind_list_free(&msg_ps->outvb);
00132 msg_ps->state = SNMP_MSG_EMPTY;
00133 }
00134
00135 static void
00136 snmp_ok_response(struct snmp_msg_pstat *msg_ps)
00137 {
00138 err_t err_ret;
00139
00140 err_ret = snmp_send_response(msg_ps);
00141 if (err_ret == ERR_MEM)
00142 {
00143
00144 }
00145 else
00146 {
00147 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event = %"S32_F"\n",msg_ps->error_status));
00148 }
00149
00150 snmp_varbind_list_free(&msg_ps->invb);
00151 snmp_varbind_list_free(&msg_ps->outvb);
00152 msg_ps->state = SNMP_MSG_EMPTY;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161 static void
00162 snmp_msg_get_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
00163 {
00164 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_get_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
00165
00166 if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
00167 {
00168 struct mib_external_node *en;
00169 struct snmp_name_ptr np;
00170
00171
00172 en = msg_ps->ext_mib_node;
00173 np = msg_ps->ext_name_ptr;
00174
00175
00176 en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
00177 if ((msg_ps->ext_object_def.instance != MIB_OBJECT_NONE) &&
00178 (msg_ps->ext_object_def.access & MIB_ACCESS_READ))
00179 {
00180 msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
00181 en->get_value_q(request_id, &msg_ps->ext_object_def);
00182 }
00183 else
00184 {
00185 en->get_object_def_pc(request_id, np.ident_len, np.ident);
00186
00187 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00188 }
00189 }
00190 else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE)
00191 {
00192 struct mib_external_node *en;
00193 struct snmp_varbind *vb;
00194
00195
00196 en = msg_ps->ext_mib_node;
00197
00198
00199 vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
00200 if (vb != NULL)
00201 {
00202 vb->next = NULL;
00203 vb->prev = NULL;
00204
00205
00206 vb->ident = msg_ps->vb_ptr->ident;
00207 vb->ident_len = msg_ps->vb_ptr->ident_len;
00208
00209 msg_ps->vb_ptr->ident = NULL;
00210 msg_ps->vb_ptr->ident_len = 0;
00211
00212 vb->value_type = msg_ps->ext_object_def.asn_type;
00213 LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
00214 vb->value_len = (u8_t)msg_ps->ext_object_def.v_len;
00215 if (vb->value_len > 0)
00216 {
00217 LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
00218 vb->value = memp_malloc(MEMP_SNMP_VALUE);
00219 if (vb->value != NULL)
00220 {
00221 en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
00222 snmp_varbind_tail_add(&msg_ps->outvb, vb);
00223
00224 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00225 msg_ps->vb_idx += 1;
00226 }
00227 else
00228 {
00229 en->get_value_pc(request_id, &msg_ps->ext_object_def);
00230 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no variable space\n"));
00231 msg_ps->vb_ptr->ident = vb->ident;
00232 msg_ps->vb_ptr->ident_len = vb->ident_len;
00233 memp_free(MEMP_SNMP_VARBIND, vb);
00234 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
00235 }
00236 }
00237 else
00238 {
00239
00240 en->get_value_a(request_id, &msg_ps->ext_object_def, 0, NULL);
00241 vb->value = NULL;
00242 snmp_varbind_tail_add(&msg_ps->outvb, vb);
00243
00244 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00245 msg_ps->vb_idx += 1;
00246 }
00247 }
00248 else
00249 {
00250 en->get_value_pc(request_id, &msg_ps->ext_object_def);
00251 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: no outvb space\n"));
00252 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
00253 }
00254 }
00255
00256 while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
00257 (msg_ps->vb_idx < msg_ps->invb.count))
00258 {
00259 struct mib_node *mn;
00260 struct snmp_name_ptr np;
00261
00262 if (msg_ps->vb_idx == 0)
00263 {
00264 msg_ps->vb_ptr = msg_ps->invb.head;
00265 }
00266 else
00267 {
00268 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
00269 }
00270
00271 if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident))
00272 {
00273 mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
00274 msg_ps->vb_ptr->ident + 4, &np);
00275 if (mn != NULL)
00276 {
00277 if (mn->node_type == MIB_NODE_EX)
00278 {
00279
00280 struct mib_external_node *en = (struct mib_external_node*)mn;
00281
00282 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
00283
00284 msg_ps->ext_mib_node = en;
00285 msg_ps->ext_name_ptr = np;
00286
00287 en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
00288 }
00289 else
00290 {
00291
00292 struct obj_def object_def;
00293
00294 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
00295 mn->get_object_def(np.ident_len, np.ident, &object_def);
00296 if ((object_def.instance != MIB_OBJECT_NONE) &&
00297 (object_def.access & MIB_ACCESS_READ))
00298 {
00299 mn = mn;
00300 }
00301 else
00302 {
00303
00304 mn = NULL;
00305 }
00306 if (mn != NULL)
00307 {
00308 struct snmp_varbind *vb;
00309
00310 msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
00311
00312 vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
00313 if (vb != NULL)
00314 {
00315 vb->next = NULL;
00316 vb->prev = NULL;
00317
00318
00319 vb->ident = msg_ps->vb_ptr->ident;
00320 vb->ident_len = msg_ps->vb_ptr->ident_len;
00321
00322 msg_ps->vb_ptr->ident = NULL;
00323 msg_ps->vb_ptr->ident_len = 0;
00324
00325 vb->value_type = object_def.asn_type;
00326 LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
00327 vb->value_len = (u8_t)object_def.v_len;
00328 if (vb->value_len > 0)
00329 {
00330 LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low",
00331 vb->value_len <= SNMP_MAX_VALUE_SIZE);
00332 vb->value = memp_malloc(MEMP_SNMP_VALUE);
00333 if (vb->value != NULL)
00334 {
00335 mn->get_value(&object_def, vb->value_len, vb->value);
00336 snmp_varbind_tail_add(&msg_ps->outvb, vb);
00337 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00338 msg_ps->vb_idx += 1;
00339 }
00340 else
00341 {
00342 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate variable space\n"));
00343 msg_ps->vb_ptr->ident = vb->ident;
00344 msg_ps->vb_ptr->ident_len = vb->ident_len;
00345 vb->ident = NULL;
00346 vb->ident_len = 0;
00347 memp_free(MEMP_SNMP_VARBIND, vb);
00348 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
00349 }
00350 }
00351 else
00352 {
00353
00354 vb->value = NULL;
00355 snmp_varbind_tail_add(&msg_ps->outvb, vb);
00356 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00357 msg_ps->vb_idx += 1;
00358 }
00359 }
00360 else
00361 {
00362 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_event: couldn't allocate outvb space\n"));
00363 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
00364 }
00365 }
00366 }
00367 }
00368 }
00369 else
00370 {
00371 mn = NULL;
00372 }
00373 if (mn == NULL)
00374 {
00375
00376 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00377 }
00378 }
00379 if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
00380 (msg_ps->vb_idx == msg_ps->invb.count))
00381 {
00382 snmp_ok_response(msg_ps);
00383 }
00384 }
00385
00386
00387
00388
00389
00390
00391
00392 static void
00393 snmp_msg_getnext_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
00394 {
00395 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
00396
00397 if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
00398 {
00399 struct mib_external_node *en;
00400
00401
00402 en = msg_ps->ext_mib_node;
00403
00404
00405 en->get_object_def_a(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1], &msg_ps->ext_object_def);
00406 if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
00407 {
00408 msg_ps->state = SNMP_MSG_EXTERNAL_GET_VALUE;
00409 en->get_value_q(request_id, &msg_ps->ext_object_def);
00410 }
00411 else
00412 {
00413 en->get_object_def_pc(request_id, 1, &msg_ps->ext_oid.id[msg_ps->ext_oid.len - 1]);
00414
00415 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00416 }
00417 }
00418 else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_VALUE)
00419 {
00420 struct mib_external_node *en;
00421 struct snmp_varbind *vb;
00422
00423
00424 en = msg_ps->ext_mib_node;
00425
00426 LWIP_ASSERT("invalid length", msg_ps->ext_object_def.v_len <= 0xff);
00427 vb = snmp_varbind_alloc(&msg_ps->ext_oid,
00428 msg_ps->ext_object_def.asn_type,
00429 (u8_t)msg_ps->ext_object_def.v_len);
00430 if (vb != NULL)
00431 {
00432 en->get_value_a(request_id, &msg_ps->ext_object_def, vb->value_len, vb->value);
00433 snmp_varbind_tail_add(&msg_ps->outvb, vb);
00434 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00435 msg_ps->vb_idx += 1;
00436 }
00437 else
00438 {
00439 en->get_value_pc(request_id, &msg_ps->ext_object_def);
00440 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_getnext_event: couldn't allocate outvb space\n"));
00441 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
00442 }
00443 }
00444
00445 while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
00446 (msg_ps->vb_idx < msg_ps->invb.count))
00447 {
00448 struct mib_node *mn;
00449 struct snmp_obj_id oid;
00450
00451 if (msg_ps->vb_idx == 0)
00452 {
00453 msg_ps->vb_ptr = msg_ps->invb.head;
00454 }
00455 else
00456 {
00457 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
00458 }
00459 if (snmp_iso_prefix_expand(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident, &oid))
00460 {
00461 if (msg_ps->vb_ptr->ident_len > 3)
00462 {
00463
00464 mn = snmp_expand_tree((struct mib_node*)&internet,
00465 msg_ps->vb_ptr->ident_len - 4,
00466 msg_ps->vb_ptr->ident + 4, &oid);
00467 }
00468 else
00469 {
00470
00471 mn = snmp_expand_tree((struct mib_node*)&internet, 0, NULL, &oid);
00472 }
00473 }
00474 else
00475 {
00476 mn = NULL;
00477 }
00478 if (mn != NULL)
00479 {
00480 if (mn->node_type == MIB_NODE_EX)
00481 {
00482
00483 struct mib_external_node *en = (struct mib_external_node*)mn;
00484
00485 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
00486
00487 msg_ps->ext_mib_node = en;
00488 msg_ps->ext_oid = oid;
00489
00490 en->get_object_def_q(en->addr_inf, request_id, 1, &oid.id[oid.len - 1]);
00491 }
00492 else
00493 {
00494
00495 struct obj_def object_def;
00496 struct snmp_varbind *vb;
00497
00498 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
00499 mn->get_object_def(1, &oid.id[oid.len - 1], &object_def);
00500
00501 LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);
00502 vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len);
00503 if (vb != NULL)
00504 {
00505 msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;
00506 mn->get_value(&object_def, object_def.v_len, vb->value);
00507 snmp_varbind_tail_add(&msg_ps->outvb, vb);
00508 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00509 msg_ps->vb_idx += 1;
00510 }
00511 else
00512 {
00513 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n"));
00514 snmp_error_response(msg_ps,SNMP_ES_TOOBIG);
00515 }
00516 }
00517 }
00518 if (mn == NULL)
00519 {
00520
00521 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00522 }
00523 }
00524 if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
00525 (msg_ps->vb_idx == msg_ps->invb.count))
00526 {
00527 snmp_ok_response(msg_ps);
00528 }
00529 }
00530
00531
00532
00533
00534
00535
00536
00537 static void
00538 snmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps)
00539 {
00540 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));
00541
00542 if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)
00543 {
00544 struct mib_external_node *en;
00545 struct snmp_name_ptr np;
00546
00547
00548 en = msg_ps->ext_mib_node;
00549 np = msg_ps->ext_name_ptr;
00550
00551
00552 en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
00553 if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
00554 {
00555 msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST;
00556 en->set_test_q(request_id, &msg_ps->ext_object_def);
00557 }
00558 else
00559 {
00560 en->get_object_def_pc(request_id, np.ident_len, np.ident);
00561
00562 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00563 }
00564 }
00565 else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST)
00566 {
00567 struct mib_external_node *en;
00568
00569
00570 en = msg_ps->ext_mib_node;
00571
00572 if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE)
00573 {
00574 if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) &&
00575 (en->set_test_a(request_id,&msg_ps->ext_object_def,
00576 msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
00577 {
00578 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00579 msg_ps->vb_idx += 1;
00580 }
00581 else
00582 {
00583 en->set_test_pc(request_id,&msg_ps->ext_object_def);
00584
00585 snmp_error_response(msg_ps,SNMP_ES_BADVALUE);
00586 }
00587 }
00588 else
00589 {
00590 en->set_test_pc(request_id,&msg_ps->ext_object_def);
00591
00592 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00593 }
00594 }
00595 else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S)
00596 {
00597 struct mib_external_node *en;
00598 struct snmp_name_ptr np;
00599
00600
00601 en = msg_ps->ext_mib_node;
00602 np = msg_ps->ext_name_ptr;
00603
00604
00605 en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);
00606 if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)
00607 {
00608 msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE;
00609 en->set_value_q(request_id, &msg_ps->ext_object_def,
00610 msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);
00611 }
00612 else
00613 {
00614 en->get_object_def_pc(request_id, np.ident_len, np.ident);
00615
00616 snmp_error_response(msg_ps,SNMP_ES_GENERROR);
00617 }
00618 }
00619 else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE)
00620 {
00621 struct mib_external_node *en;
00622
00623
00624 en = msg_ps->ext_mib_node;
00625 en->set_value_a(request_id, &msg_ps->ext_object_def,
00626 msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value);
00627
00628
00629 msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
00630 msg_ps->vb_idx += 1;
00631 }
00632
00633
00634 while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
00635 (msg_ps->vb_idx < msg_ps->invb.count))
00636 {
00637 struct mib_node *mn;
00638 struct snmp_name_ptr np;
00639
00640 if (msg_ps->vb_idx == 0)
00641 {
00642 msg_ps->vb_ptr = msg_ps->invb.head;
00643 }
00644 else
00645 {
00646 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
00647 }
00648
00649 if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len, msg_ps->vb_ptr->ident))
00650 {
00651 mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
00652 msg_ps->vb_ptr->ident + 4, &np);
00653 if (mn != NULL)
00654 {
00655 if (mn->node_type == MIB_NODE_EX)
00656 {
00657
00658 struct mib_external_node *en = (struct mib_external_node*)mn;
00659
00660 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;
00661
00662 msg_ps->ext_mib_node = en;
00663 msg_ps->ext_name_ptr = np;
00664
00665 en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
00666 }
00667 else
00668 {
00669
00670 struct obj_def object_def;
00671
00672 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;
00673 mn->get_object_def(np.ident_len, np.ident, &object_def);
00674 if (object_def.instance != MIB_OBJECT_NONE)
00675 {
00676 mn = mn;
00677 }
00678 else
00679 {
00680
00681 mn = NULL;
00682 }
00683 if (mn != NULL)
00684 {
00685 msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST;
00686
00687 if (object_def.access & MIB_ACCESS_WRITE)
00688 {
00689 if ((object_def.asn_type == msg_ps->vb_ptr->value_type) &&
00690 (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))
00691 {
00692 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00693 msg_ps->vb_idx += 1;
00694 }
00695 else
00696 {
00697
00698 snmp_error_response(msg_ps,SNMP_ES_BADVALUE);
00699 }
00700 }
00701 else
00702 {
00703
00704 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00705 }
00706 }
00707 }
00708 }
00709 }
00710 else
00711 {
00712 mn = NULL;
00713 }
00714 if (mn == NULL)
00715 {
00716
00717 snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);
00718 }
00719 }
00720
00721 if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&
00722 (msg_ps->vb_idx == msg_ps->invb.count))
00723 {
00724 msg_ps->vb_idx = 0;
00725 msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
00726 }
00727
00728
00729 while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&
00730 (msg_ps->vb_idx < msg_ps->invb.count))
00731 {
00732 struct mib_node *mn;
00733 struct snmp_name_ptr np;
00734
00735 if (msg_ps->vb_idx == 0)
00736 {
00737 msg_ps->vb_ptr = msg_ps->invb.head;
00738 }
00739 else
00740 {
00741 msg_ps->vb_ptr = msg_ps->vb_ptr->next;
00742 }
00743
00744 mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,
00745 msg_ps->vb_ptr->ident + 4, &np);
00746
00747
00748 if (mn != NULL)
00749 {
00750 if (mn->node_type == MIB_NODE_EX)
00751 {
00752
00753 struct mib_external_node *en = (struct mib_external_node*)mn;
00754
00755 msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S;
00756
00757 msg_ps->ext_mib_node = en;
00758 msg_ps->ext_name_ptr = np;
00759
00760 en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);
00761 }
00762 else
00763 {
00764
00765 struct obj_def object_def;
00766
00767 msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S;
00768 mn->get_object_def(np.ident_len, np.ident, &object_def);
00769 msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;
00770 mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);
00771 msg_ps->vb_idx += 1;
00772 }
00773 }
00774 }
00775 if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&
00776 (msg_ps->vb_idx == msg_ps->invb.count))
00777 {
00778
00779
00780
00781 msg_ps->outvb = msg_ps->invb;
00782 msg_ps->invb.head = NULL;
00783 msg_ps->invb.tail = NULL;
00784 msg_ps->invb.count = 0;
00785 snmp_ok_response(msg_ps);
00786 }
00787 }
00788
00789
00790
00791
00792
00793
00794
00795
00796 void
00797 snmp_msg_event(u8_t request_id)
00798 {
00799 struct snmp_msg_pstat *msg_ps;
00800
00801 if (request_id < SNMP_CONCURRENT_REQUESTS)
00802 {
00803 msg_ps = &msg_input_list[request_id];
00804 if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ)
00805 {
00806 snmp_msg_getnext_event(request_id, msg_ps);
00807 }
00808 else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ)
00809 {
00810 snmp_msg_get_event(request_id, msg_ps);
00811 }
00812 else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)
00813 {
00814 snmp_msg_set_event(request_id, msg_ps);
00815 }
00816 }
00817 }
00818
00819
00820
00821 static void
00822 snmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
00823 {
00824 struct snmp_msg_pstat *msg_ps;
00825 u8_t req_idx;
00826 err_t err_ret;
00827 u16_t payload_len = p->tot_len;
00828 u16_t payload_ofs = 0;
00829 u16_t varbind_ofs = 0;
00830
00831
00832 LWIP_UNUSED_ARG(arg);
00833
00834
00835 msg_ps = &msg_input_list[0];
00836 req_idx = 0;
00837 while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))
00838 {
00839 req_idx++;
00840 msg_ps++;
00841 }
00842 if (req_idx == SNMP_CONCURRENT_REQUESTS)
00843 {
00844
00845 pbuf_free(p);
00846 return;
00847 }
00848
00849
00850 snmp_inc_snmpinpkts();
00851
00852 msg_ps->pcb = pcb;
00853
00854 msg_ps->sip = *addr;
00855
00856 msg_ps->sp = port;
00857
00858
00859 err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);
00860
00861
00862 if ((err_ret != ERR_OK) ||
00863 ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) &&
00864 (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) &&
00865 (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) ||
00866 ((msg_ps->error_status != SNMP_ES_NOERROR) ||
00867 (msg_ps->error_index != 0)) )
00868 {
00869
00870 pbuf_free(p);
00871 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));
00872 return;
00873 }
00874 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));
00875
00876
00877
00878 err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);
00879
00880 pbuf_free(p);
00881 if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0))
00882 {
00883
00884
00885
00886 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));
00887 return;
00888 }
00889
00890 msg_ps->error_status = SNMP_ES_NOERROR;
00891 msg_ps->error_index = 0;
00892
00893 msg_ps->state = SNMP_MSG_SEARCH_OBJ;
00894
00895 msg_ps->vb_idx = 0;
00896
00897 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));
00898
00899
00900 snmp_msg_event(req_idx);
00901 }
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913
00914
00915 static err_t
00916 snmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat)
00917 {
00918 err_t derr;
00919 u16_t len, ofs_base;
00920 u8_t len_octets;
00921 u8_t type;
00922 s32_t version;
00923
00924 ofs_base = ofs;
00925 snmp_asn1_dec_type(p, ofs, &type);
00926 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
00927 if ((derr != ERR_OK) ||
00928 (pdu_len != (1 + len_octets + len)) ||
00929 (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))
00930 {
00931 snmp_inc_snmpinasnparseerrs();
00932 return ERR_ARG;
00933 }
00934 ofs += (1 + len_octets);
00935 snmp_asn1_dec_type(p, ofs, &type);
00936 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
00937 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
00938 {
00939
00940 snmp_inc_snmpinasnparseerrs();
00941 return ERR_ARG;
00942 }
00943 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version);
00944 if (derr != ERR_OK)
00945 {
00946
00947 snmp_inc_snmpinasnparseerrs();
00948 return ERR_ARG;
00949 }
00950 if (version != 0)
00951 {
00952
00953 snmp_inc_snmpinbadversions();
00954 return ERR_ARG;
00955 }
00956 ofs += (1 + len_octets + len);
00957 snmp_asn1_dec_type(p, ofs, &type);
00958 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
00959 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)))
00960 {
00961
00962 snmp_inc_snmpinasnparseerrs();
00963 return ERR_ARG;
00964 }
00965 derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community);
00966 if (derr != ERR_OK)
00967 {
00968 snmp_inc_snmpinasnparseerrs();
00969 return ERR_ARG;
00970 }
00971
00972 len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN));
00973 m_stat->community[len] = 0;
00974 m_stat->com_strlen = (u8_t)len;
00975 if (strncmp(snmp_publiccommunity, (const char*)m_stat->community, SNMP_COMMUNITY_STR_LEN) != 0)
00976 {
00977
00978 snmp_inc_snmpinbadcommunitynames();
00979 snmp_authfail_trap();
00980 return ERR_ARG;
00981 }
00982 ofs += (1 + len_octets + len);
00983 snmp_asn1_dec_type(p, ofs, &type);
00984 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
00985 if (derr != ERR_OK)
00986 {
00987 snmp_inc_snmpinasnparseerrs();
00988 return ERR_ARG;
00989 }
00990 switch(type)
00991 {
00992 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_REQ):
00993
00994 snmp_inc_snmpingetrequests();
00995 derr = ERR_OK;
00996 break;
00997 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_NEXT_REQ):
00998
00999 snmp_inc_snmpingetnexts();
01000 derr = ERR_OK;
01001 break;
01002 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_GET_RESP):
01003
01004 snmp_inc_snmpingetresponses();
01005 derr = ERR_ARG;
01006 break;
01007 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_SET_REQ):
01008
01009 snmp_inc_snmpinsetrequests();
01010 derr = ERR_OK;
01011 break;
01012 case (SNMP_ASN1_CONTXT | SNMP_ASN1_CONSTR | SNMP_ASN1_PDU_TRAP):
01013
01014 snmp_inc_snmpintraps();
01015 derr = ERR_ARG;
01016 break;
01017 default:
01018 snmp_inc_snmpinasnparseerrs();
01019 derr = ERR_ARG;
01020 break;
01021 }
01022 if (derr != ERR_OK)
01023 {
01024
01025 return ERR_ARG;
01026 }
01027 m_stat->rt = type & 0x1F;
01028 ofs += (1 + len_octets);
01029 if (len != (pdu_len - (ofs - ofs_base)))
01030 {
01031
01032 snmp_inc_snmpinasnparseerrs();
01033 return ERR_ARG;
01034 }
01035 snmp_asn1_dec_type(p, ofs, &type);
01036 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
01037 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
01038 {
01039
01040 snmp_inc_snmpinasnparseerrs();
01041 return ERR_ARG;
01042 }
01043 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->rid);
01044 if (derr != ERR_OK)
01045 {
01046
01047 snmp_inc_snmpinasnparseerrs();
01048 return ERR_ARG;
01049 }
01050 ofs += (1 + len_octets + len);
01051 snmp_asn1_dec_type(p, ofs, &type);
01052 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
01053 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
01054 {
01055
01056 snmp_inc_snmpinasnparseerrs();
01057 return ERR_ARG;
01058 }
01059
01060
01061 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_status);
01062 if (derr != ERR_OK)
01063 {
01064
01065 snmp_inc_snmpinasnparseerrs();
01066 return ERR_ARG;
01067 }
01068 switch (m_stat->error_status)
01069 {
01070 case SNMP_ES_TOOBIG:
01071 snmp_inc_snmpintoobigs();
01072 break;
01073 case SNMP_ES_NOSUCHNAME:
01074 snmp_inc_snmpinnosuchnames();
01075 break;
01076 case SNMP_ES_BADVALUE:
01077 snmp_inc_snmpinbadvalues();
01078 break;
01079 case SNMP_ES_READONLY:
01080 snmp_inc_snmpinreadonlys();
01081 break;
01082 case SNMP_ES_GENERROR:
01083 snmp_inc_snmpingenerrs();
01084 break;
01085 }
01086 ofs += (1 + len_octets + len);
01087 snmp_asn1_dec_type(p, ofs, &type);
01088 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
01089 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))
01090 {
01091
01092 snmp_inc_snmpinasnparseerrs();
01093 return ERR_ARG;
01094 }
01095
01096
01097 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &m_stat->error_index);
01098 if (derr != ERR_OK)
01099 {
01100
01101 snmp_inc_snmpinasnparseerrs();
01102 return ERR_ARG;
01103 }
01104 ofs += (1 + len_octets + len);
01105 *ofs_ret = ofs;
01106 return ERR_OK;
01107 }
01108
01109 static err_t
01110 snmp_pdu_dec_varbindlist(struct pbuf *p, u16_t ofs, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat)
01111 {
01112 err_t derr;
01113 u16_t len, vb_len;
01114 u8_t len_octets;
01115 u8_t type;
01116
01117
01118 snmp_asn1_dec_type(p, ofs, &type);
01119 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &vb_len);
01120 if ((derr != ERR_OK) ||
01121 (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))
01122 {
01123 snmp_inc_snmpinasnparseerrs();
01124 return ERR_ARG;
01125 }
01126 ofs += (1 + len_octets);
01127
01128
01129 m_stat->invb.count = 0;
01130 m_stat->invb.head = NULL;
01131 m_stat->invb.tail = NULL;
01132
01133 while (vb_len > 0)
01134 {
01135 struct snmp_obj_id oid, oid_value;
01136 struct snmp_varbind *vb;
01137
01138 snmp_asn1_dec_type(p, ofs, &type);
01139 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
01140 if ((derr != ERR_OK) ||
01141 (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)) ||
01142 (len == 0) || (len > vb_len))
01143 {
01144 snmp_inc_snmpinasnparseerrs();
01145
01146 snmp_varbind_list_free(&m_stat->invb);
01147 return ERR_ARG;
01148 }
01149 ofs += (1 + len_octets);
01150 vb_len -= (1 + len_octets);
01151
01152 snmp_asn1_dec_type(p, ofs, &type);
01153 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
01154 if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID)))
01155 {
01156
01157 snmp_inc_snmpinasnparseerrs();
01158
01159 snmp_varbind_list_free(&m_stat->invb);
01160 return ERR_ARG;
01161 }
01162 derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid);
01163 if (derr != ERR_OK)
01164 {
01165
01166 snmp_inc_snmpinasnparseerrs();
01167
01168 snmp_varbind_list_free(&m_stat->invb);
01169 return ERR_ARG;
01170 }
01171 ofs += (1 + len_octets + len);
01172 vb_len -= (1 + len_octets + len);
01173
01174 snmp_asn1_dec_type(p, ofs, &type);
01175 derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);
01176 if (derr != ERR_OK)
01177 {
01178
01179 snmp_inc_snmpinasnparseerrs();
01180
01181 snmp_varbind_list_free(&m_stat->invb);
01182 return ERR_ARG;
01183 }
01184
01185 switch (type)
01186 {
01187 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG):
01188 vb = snmp_varbind_alloc(&oid, type, sizeof(s32_t));
01189 if (vb != NULL)
01190 {
01191 s32_t *vptr = (s32_t*)vb->value;
01192
01193 derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, vptr);
01194 snmp_varbind_tail_add(&m_stat->invb, vb);
01195 }
01196 else
01197 {
01198 derr = ERR_ARG;
01199 }
01200 break;
01201 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_COUNTER):
01202 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_GAUGE):
01203 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_TIMETICKS):
01204 vb = snmp_varbind_alloc(&oid, type, sizeof(u32_t));
01205 if (vb != NULL)
01206 {
01207 u32_t *vptr = (u32_t*)vb->value;
01208
01209 derr = snmp_asn1_dec_u32t(p, ofs + 1 + len_octets, len, vptr);
01210 snmp_varbind_tail_add(&m_stat->invb, vb);
01211 }
01212 else
01213 {
01214 derr = ERR_ARG;
01215 }
01216 break;
01217 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR):
01218 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_OPAQUE):
01219 LWIP_ASSERT("invalid length", len <= 0xff);
01220 vb = snmp_varbind_alloc(&oid, type, (u8_t)len);
01221 if (vb != NULL)
01222 {
01223 derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
01224 snmp_varbind_tail_add(&m_stat->invb, vb);
01225 }
01226 else
01227 {
01228 derr = ERR_ARG;
01229 }
01230 break;
01231 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_NUL):
01232 vb = snmp_varbind_alloc(&oid, type, 0);
01233 if (vb != NULL)
01234 {
01235 snmp_varbind_tail_add(&m_stat->invb, vb);
01236 derr = ERR_OK;
01237 }
01238 else
01239 {
01240 derr = ERR_ARG;
01241 }
01242 break;
01243 case (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OBJ_ID):
01244 derr = snmp_asn1_dec_oid(p, ofs + 1 + len_octets, len, &oid_value);
01245 if (derr == ERR_OK)
01246 {
01247 vb = snmp_varbind_alloc(&oid, type, oid_value.len * sizeof(s32_t));
01248 if (vb != NULL)
01249 {
01250 u8_t i = oid_value.len;
01251 s32_t *vptr = (s32_t*)vb->value;
01252
01253 while(i > 0)
01254 {
01255 i--;
01256 vptr[i] = oid_value.id[i];
01257 }
01258 snmp_varbind_tail_add(&m_stat->invb, vb);
01259 derr = ERR_OK;
01260 }
01261 else
01262 {
01263 derr = ERR_ARG;
01264 }
01265 }
01266 break;
01267 case (SNMP_ASN1_APPLIC | SNMP_ASN1_PRIMIT | SNMP_ASN1_IPADDR):
01268 if (len == 4)
01269 {
01270
01271 vb = snmp_varbind_alloc(&oid, type, 4);
01272 if (vb != NULL)
01273 {
01274 derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, vb->value_len, (u8_t*)vb->value);
01275 snmp_varbind_tail_add(&m_stat->invb, vb);
01276 }
01277 else
01278 {
01279 derr = ERR_ARG;
01280 }
01281 }
01282 else
01283 {
01284 derr = ERR_ARG;
01285 }
01286 break;
01287 default:
01288 derr = ERR_ARG;
01289 break;
01290 }
01291 if (derr != ERR_OK)
01292 {
01293 snmp_inc_snmpinasnparseerrs();
01294
01295 snmp_varbind_list_free(&m_stat->invb);
01296 return ERR_ARG;
01297 }
01298 ofs += (1 + len_octets + len);
01299 vb_len -= (1 + len_octets + len);
01300 }
01301
01302 if (m_stat->rt == SNMP_ASN1_PDU_SET_REQ)
01303 {
01304 snmp_add_snmpintotalsetvars(m_stat->invb.count);
01305 }
01306 else
01307 {
01308 snmp_add_snmpintotalreqvars(m_stat->invb.count);
01309 }
01310
01311 *ofs_ret = ofs;
01312 return ERR_OK;
01313 }
01314
01315 struct snmp_varbind*
01316 snmp_varbind_alloc(struct snmp_obj_id *oid, u8_t type, u8_t len)
01317 {
01318 struct snmp_varbind *vb;
01319
01320 vb = (struct snmp_varbind *)memp_malloc(MEMP_SNMP_VARBIND);
01321 if (vb != NULL)
01322 {
01323 u8_t i;
01324
01325 vb->next = NULL;
01326 vb->prev = NULL;
01327 i = oid->len;
01328 vb->ident_len = i;
01329 if (i > 0)
01330 {
01331 LWIP_ASSERT("SNMP_MAX_TREE_DEPTH is configured too low", i <= SNMP_MAX_TREE_DEPTH);
01332
01333 vb->ident = (s32_t*)memp_malloc(MEMP_SNMP_VALUE);
01334 if (vb->ident == NULL)
01335 {
01336 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate ident value space\n"));
01337 memp_free(MEMP_SNMP_VARBIND, vb);
01338 return NULL;
01339 }
01340 while(i > 0)
01341 {
01342 i--;
01343 vb->ident[i] = oid->id[i];
01344 }
01345 }
01346 else
01347 {
01348
01349 vb->ident = NULL;
01350 }
01351 vb->value_type = type;
01352 vb->value_len = len;
01353 if (len > 0)
01354 {
01355 LWIP_ASSERT("SNMP_MAX_OCTET_STRING_LEN is configured too low", vb->value_len <= SNMP_MAX_VALUE_SIZE);
01356
01357 vb->value = memp_malloc(MEMP_SNMP_VALUE);
01358 if (vb->value == NULL)
01359 {
01360 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate value space\n"));
01361 if (vb->ident != NULL)
01362 {
01363 memp_free(MEMP_SNMP_VALUE, vb->ident);
01364 }
01365 memp_free(MEMP_SNMP_VARBIND, vb);
01366 return NULL;
01367 }
01368 }
01369 else
01370 {
01371
01372 vb->value = NULL;
01373 }
01374 }
01375 else
01376 {
01377 LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_varbind_alloc: couldn't allocate varbind space\n"));
01378 }
01379 return vb;
01380 }
01381
01382 void
01383 snmp_varbind_free(struct snmp_varbind *vb)
01384 {
01385 if (vb->value != NULL )
01386 {
01387 memp_free(MEMP_SNMP_VALUE, vb->value);
01388 }
01389 if (vb->ident != NULL )
01390 {
01391 memp_free(MEMP_SNMP_VALUE, vb->ident);
01392 }
01393 memp_free(MEMP_SNMP_VARBIND, vb);
01394 }
01395
01396 void
01397 snmp_varbind_list_free(struct snmp_varbind_root *root)
01398 {
01399 struct snmp_varbind *vb, *prev;
01400
01401 vb = root->tail;
01402 while ( vb != NULL )
01403 {
01404 prev = vb->prev;
01405 snmp_varbind_free(vb);
01406 vb = prev;
01407 }
01408 root->count = 0;
01409 root->head = NULL;
01410 root->tail = NULL;
01411 }
01412
01413 void
01414 snmp_varbind_tail_add(struct snmp_varbind_root *root, struct snmp_varbind *vb)
01415 {
01416 if (root->count == 0)
01417 {
01418
01419 root->head = vb;
01420 root->tail = vb;
01421 }
01422 else
01423 {
01424
01425 root->tail->next = vb;
01426 vb->prev = root->tail;
01427 root->tail = vb;
01428 }
01429 root->count += 1;
01430 }
01431
01432 struct snmp_varbind*
01433 snmp_varbind_tail_remove(struct snmp_varbind_root *root)
01434 {
01435 struct snmp_varbind* vb;
01436
01437 if (root->count > 0)
01438 {
01439
01440 vb = root->tail;
01441 root->tail = vb->prev;
01442 vb->prev->next = NULL;
01443 root->count -= 1;
01444 }
01445 else
01446 {
01447
01448 vb = NULL;
01449 }
01450 return vb;
01451 }
01452
01453 #endif