⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 msg_in.c

📁 lwip-1.4.0
💻 C
📖 第 1 页 / 共 3 页
字号:
        /* internal object */        struct obj_def object_def;        struct snmp_varbind *vb;        msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;        mn->get_object_def(1, &oid.id[oid.len - 1], &object_def);        LWIP_ASSERT("invalid length", object_def.v_len <= 0xff);        vb = snmp_varbind_alloc(&oid, object_def.asn_type, (u8_t)object_def.v_len);        if (vb != NULL)        {          msg_ps->state = SNMP_MSG_INTERNAL_GET_VALUE;          mn->get_value(&object_def, object_def.v_len, vb->value);          snmp_varbind_tail_add(&msg_ps->outvb, vb);          msg_ps->state = SNMP_MSG_SEARCH_OBJ;          msg_ps->vb_idx += 1;        }        else        {          LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv couldn't allocate outvb space\n"));          snmp_error_response(msg_ps,SNMP_ES_TOOBIG);        }      }    }    if (mn == NULL)    {      /* mn == NULL, noSuchName */      snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);    }  }  if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&      (msg_ps->vb_idx == msg_ps->invb.count))  {    snmp_ok_response(msg_ps);  }}/** * Service an internal or external event for SNMP SET. * * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) * @param msg_ps points to the assosicated message process state */static voidsnmp_msg_set_event(u8_t request_id, struct snmp_msg_pstat *msg_ps){  LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_msg_set_event: msg_ps->state==%"U16_F"\n",(u16_t)msg_ps->state));  if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF)  {    struct mib_external_node *en;    struct snmp_name_ptr np;    /* get_object_def() answer*/    en = msg_ps->ext_mib_node;    np = msg_ps->ext_name_ptr;    /* translate answer into a known lifeform */    en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);    if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)    {      msg_ps->state = SNMP_MSG_EXTERNAL_SET_TEST;      en->set_test_q(request_id, &msg_ps->ext_object_def);    }    else    {      en->get_object_def_pc(request_id, np.ident_len, np.ident);      /* search failed, object id points to unknown object (nosuchname) */      snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);    }  }  else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_TEST)  {    struct mib_external_node *en;    /* set_test() answer*/    en = msg_ps->ext_mib_node;    if (msg_ps->ext_object_def.access & MIB_ACCESS_WRITE)    {       if ((msg_ps->ext_object_def.asn_type == msg_ps->vb_ptr->value_type) &&           (en->set_test_a(request_id,&msg_ps->ext_object_def,                           msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))      {        msg_ps->state = SNMP_MSG_SEARCH_OBJ;        msg_ps->vb_idx += 1;      }      else      {        en->set_test_pc(request_id,&msg_ps->ext_object_def);        /* bad value */        snmp_error_response(msg_ps,SNMP_ES_BADVALUE);      }    }    else    {      en->set_test_pc(request_id,&msg_ps->ext_object_def);      /* object not available for set */      snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);    }  }  else if (msg_ps->state == SNMP_MSG_EXTERNAL_GET_OBJDEF_S)  {    struct mib_external_node *en;    struct snmp_name_ptr np;    /* get_object_def() answer*/    en = msg_ps->ext_mib_node;    np = msg_ps->ext_name_ptr;    /* translate answer into a known lifeform */    en->get_object_def_a(request_id, np.ident_len, np.ident, &msg_ps->ext_object_def);    if (msg_ps->ext_object_def.instance != MIB_OBJECT_NONE)    {      msg_ps->state = SNMP_MSG_EXTERNAL_SET_VALUE;      en->set_value_q(request_id, &msg_ps->ext_object_def,                      msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);    }    else    {      en->get_object_def_pc(request_id, np.ident_len, np.ident);      /* set_value failed, object has disappeared for some odd reason?? */      snmp_error_response(msg_ps,SNMP_ES_GENERROR);    }  }  else if (msg_ps->state == SNMP_MSG_EXTERNAL_SET_VALUE)  {    struct mib_external_node *en;    /** set_value_a() */    en = msg_ps->ext_mib_node;    en->set_value_a(request_id, &msg_ps->ext_object_def,      msg_ps->vb_ptr->value_len, msg_ps->vb_ptr->value);    /** @todo use set_value_pc() if toobig */    msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;    msg_ps->vb_idx += 1;  }  /* test all values before setting */  while ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&         (msg_ps->vb_idx < msg_ps->invb.count))  {    struct mib_node *mn;    struct snmp_name_ptr np;    if (msg_ps->vb_idx == 0)    {      msg_ps->vb_ptr = msg_ps->invb.head;    }    else    {      msg_ps->vb_ptr = msg_ps->vb_ptr->next;    }    /** test object identifier for .iso.org.dod.internet prefix */    if (snmp_iso_prefix_tst(msg_ps->vb_ptr->ident_len,  msg_ps->vb_ptr->ident))    {      mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,                             msg_ps->vb_ptr->ident + 4, &np);      if (mn != NULL)      {        if (mn->node_type == MIB_NODE_EX)        {          /* external object */          struct mib_external_node *en = (struct mib_external_node*)mn;          msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF;          /* save en && args in msg_ps!! */          msg_ps->ext_mib_node = en;          msg_ps->ext_name_ptr = np;          en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);        }        else        {          /* internal object */          struct obj_def object_def;          msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF;          mn->get_object_def(np.ident_len, np.ident, &object_def);          if (object_def.instance != MIB_OBJECT_NONE)          {            mn = mn;          }          else          {            /* search failed, object id points to unknown object (nosuchname) */            mn = NULL;          }          if (mn != NULL)          {            msg_ps->state = SNMP_MSG_INTERNAL_SET_TEST;            if (object_def.access & MIB_ACCESS_WRITE)            {              if ((object_def.asn_type == msg_ps->vb_ptr->value_type) &&                  (mn->set_test(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value) != 0))              {                msg_ps->state = SNMP_MSG_SEARCH_OBJ;                msg_ps->vb_idx += 1;              }              else              {                /* bad value */                snmp_error_response(msg_ps,SNMP_ES_BADVALUE);              }            }            else            {              /* object not available for set */              snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);            }          }        }      }    }    else    {      mn = NULL;    }    if (mn == NULL)    {      /* mn == NULL, noSuchName */      snmp_error_response(msg_ps,SNMP_ES_NOSUCHNAME);    }  }  if ((msg_ps->state == SNMP_MSG_SEARCH_OBJ) &&      (msg_ps->vb_idx == msg_ps->invb.count))  {    msg_ps->vb_idx = 0;    msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;  }  /* set all values "atomically" (be as "atomic" as possible) */  while ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&         (msg_ps->vb_idx < msg_ps->invb.count))  {    struct mib_node *mn;    struct snmp_name_ptr np;    if (msg_ps->vb_idx == 0)    {      msg_ps->vb_ptr = msg_ps->invb.head;    }    else    {      msg_ps->vb_ptr = msg_ps->vb_ptr->next;    }    /* skip iso prefix test, was done previously while settesting() */    mn = snmp_search_tree((struct mib_node*)&internet, msg_ps->vb_ptr->ident_len - 4,                           msg_ps->vb_ptr->ident + 4, &np);    /* check if object is still available       (e.g. external hot-plug thingy present?) */    if (mn != NULL)    {      if (mn->node_type == MIB_NODE_EX)      {        /* external object */        struct mib_external_node *en = (struct mib_external_node*)mn;        msg_ps->state = SNMP_MSG_EXTERNAL_GET_OBJDEF_S;        /* save en && args in msg_ps!! */        msg_ps->ext_mib_node = en;        msg_ps->ext_name_ptr = np;        en->get_object_def_q(en->addr_inf, request_id, np.ident_len, np.ident);      }      else      {        /* internal object */        struct obj_def object_def;        msg_ps->state = SNMP_MSG_INTERNAL_GET_OBJDEF_S;        mn->get_object_def(np.ident_len, np.ident, &object_def);        msg_ps->state = SNMP_MSG_INTERNAL_SET_VALUE;        mn->set_value(&object_def,msg_ps->vb_ptr->value_len,msg_ps->vb_ptr->value);        msg_ps->vb_idx += 1;      }    }  }  if ((msg_ps->state == SNMP_MSG_INTERNAL_SET_VALUE) &&      (msg_ps->vb_idx == msg_ps->invb.count))  {    /* simply echo the input if we can set it       @todo do we need to return the actual value?       e.g. if value is silently modified or behaves sticky? */    msg_ps->outvb = msg_ps->invb;    msg_ps->invb.head = NULL;    msg_ps->invb.tail = NULL;    msg_ps->invb.count = 0;    snmp_ok_response(msg_ps);  }}/** * Handle one internal or external event. * Called for one async event. (recv external/private answer) * * @param request_id identifies requests from 0 to (SNMP_CONCURRENT_REQUESTS-1) */voidsnmp_msg_event(u8_t request_id){  struct snmp_msg_pstat *msg_ps;  if (request_id < SNMP_CONCURRENT_REQUESTS)  {    msg_ps = &msg_input_list[request_id];    if (msg_ps->rt == SNMP_ASN1_PDU_GET_NEXT_REQ)    {      snmp_msg_getnext_event(request_id, msg_ps);    }    else if (msg_ps->rt == SNMP_ASN1_PDU_GET_REQ)    {      snmp_msg_get_event(request_id, msg_ps);    }    else if(msg_ps->rt == SNMP_ASN1_PDU_SET_REQ)    {      snmp_msg_set_event(request_id, msg_ps);    }  }}/* lwIP UDP receive callback function */static voidsnmp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, ip_addr_t *addr, u16_t port){  struct snmp_msg_pstat *msg_ps;  u8_t req_idx;  err_t err_ret;  u16_t payload_len = p->tot_len;  u16_t payload_ofs = 0;  u16_t varbind_ofs = 0;  /* suppress unused argument warning */  LWIP_UNUSED_ARG(arg);  /* traverse input message process list, look for SNMP_MSG_EMPTY */  msg_ps = &msg_input_list[0];  req_idx = 0;  while ((req_idx < SNMP_CONCURRENT_REQUESTS) && (msg_ps->state != SNMP_MSG_EMPTY))  {    req_idx++;    msg_ps++;  }  if (req_idx == SNMP_CONCURRENT_REQUESTS)  {    /* exceeding number of concurrent requests */    pbuf_free(p);    return;  }  /* accepting request */  snmp_inc_snmpinpkts();  /* record used 'protocol control block' */  msg_ps->pcb = pcb;  /* source address (network order) */  msg_ps->sip = *addr;  /* source port (host order (lwIP oddity)) */  msg_ps->sp = port;  /* check total length, version, community, pdu type */  err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);  /* Only accept requests and requests without error (be robust) */  /* Reject response and trap headers or error requests as input! */  if ((err_ret != ERR_OK) ||      ((msg_ps->rt != SNMP_ASN1_PDU_GET_REQ) &&       (msg_ps->rt != SNMP_ASN1_PDU_GET_NEXT_REQ) &&       (msg_ps->rt != SNMP_ASN1_PDU_SET_REQ)) ||      ((msg_ps->error_status != SNMP_ES_NOERROR) ||       (msg_ps->error_index != 0)) )  {    /* header check failed drop request silently, do not return error! */    pbuf_free(p);    LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));    return;  }  LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv ok, community %s\n", msg_ps->community));  /* Builds a list of variable bindings. Copy the varbinds from the pbuf    chain to glue them when these are divided over two or more pbuf's. */  err_ret = snmp_pdu_dec_varbindlist(p, varbind_ofs, &varbind_ofs, msg_ps);  /* we've decoded the incoming message, release input msg now */  pbuf_free(p);  if ((err_ret != ERR_OK) || (msg_ps->invb.count == 0))  {    /* varbind-list decode failed, or varbind list empty.       drop request silently, do not return error!       (errors are only returned for a specific varbind failure) */    LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));    return;  }  msg_ps->error_status = SNMP_ES_NOERROR;  msg_ps->error_index = 0;  /* find object for each variable binding */  msg_ps->state = SNMP_MSG_SEARCH_OBJ;  /* first variable binding from list to inspect */  msg_ps->vb_idx = 0;  LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_recv varbind cnt=%"U16_F"\n",(u16_t)msg_ps->invb.count));  /* handle input event and as much objects as possible in one go */  snmp_msg_event(req_idx);}/** * Checks and decodes incoming SNMP message header, logs header errors. * * @param p points to pbuf chain of SNMP message (UDP payload) * @param ofs points to first octet of SNMP message * @param pdu_len the length of the UDP payload * @param ofs_ret returns the ofset of the variable bindings * @param m_stat points to the current message request state return * @return * - ERR_OK SNMP header is sane and accepted * - ERR_ARG SNMP header is either malformed or rejected */static err_tsnmp_pdu_header_check(struct pbuf *p, u16_t ofs, u16_t pdu_len, u16_t *ofs_ret, struct snmp_msg_pstat *m_stat){  err_t derr;  u16_t len, ofs_base;  u8_t  len_octets;  u8_t  type;  s32_t version;  ofs_base = ofs;  snmp_asn1_dec_type(p, ofs, &type);  derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);  if ((derr != ERR_OK) ||      (pdu_len != (1 + len_octets + len)) ||      (type != (SNMP_ASN1_UNIV | SNMP_ASN1_CONSTR | SNMP_ASN1_SEQ)))  {    snmp_inc_snmpinasnparseerrs();    return ERR_ARG;  }  ofs += (1 + len_octets);  snmp_asn1_dec_type(p, ofs, &type);  derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);  if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_INTEG)))  {    /* can't decode or no integer (version) */    snmp_inc_snmpinasnparseerrs();    return ERR_ARG;  }  derr = snmp_asn1_dec_s32t(p, ofs + 1 + len_octets, len, &version);  if (derr != ERR_OK)  {    /* can't decode */    snmp_inc_snmpinasnparseerrs();    return ERR_ARG;  }  if (version != 0)  {    /* not version 1 */    snmp_inc_snmpinbadversions();    return ERR_ARG;  }  ofs += (1 + len_octets + len);  snmp_asn1_dec_type(p, ofs, &type);  derr = snmp_asn1_dec_length(p, ofs+1, &len_octets, &len);  if ((derr != ERR_OK) || (type != (SNMP_ASN1_UNIV | SNMP_ASN1_PRIMIT | SNMP_ASN1_OC_STR)))  {    /* can't decode or no octet string (community) */    snmp_inc_snmpinasnparseerrs();    return ERR_ARG;  }  derr = snmp_asn1_dec_raw(p, ofs + 1 + len_octets, len, SNMP_COMMUNITY_STR_LEN, m_stat->community);  if (derr != ERR_OK)  {    snmp_inc_snmpinasnparseerrs();    return ERR_ARG;  }  /* add zero terminator */  len = ((len < (SNMP_COMMUNITY_STR_LEN))?(len):(SNMP_COMMUNITY_STR_LEN));  m_stat->community[len] = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -