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