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

📄 msg_in.c

📁 《嵌入式网络系统设计-基于Atmel ARM7 系列》这个本书的光盘资料
💻 C
📖 第 1 页 / 共 3 页
字号:
        {          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;    struct snmp_name_ptr np;    /* set_test() answer*/    en = msg_ps->ext_mib_node;    np = msg_ps->ext_name_ptr;    if (msg_ps->ext_object_def.access == MIB_OBJECT_READ_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() @todo: use reply value?? */    en = msg_ps->ext_mib_node;    en->set_value_a(request_id, &msg_ps->ext_object_def, 0, NULL);    /** @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);    }    else    {      mn = NULL;    }    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_OBJECT_READ_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);          }        }      }    }    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, struct ip_addr *addr, u16_t port){  struct udp_hdr *udphdr;  /* suppress unused argument warning */  if (arg);  /* peek in the UDP header (goto IP payload) */  pbuf_header(p, UDP_HLEN);  udphdr = p->payload;  /* check if datagram is really directed at us (including broadcast requests) */  if ((pcb == snmp1_pcb) && (ntohs(udphdr->dest) == 161))  {    struct snmp_msg_pstat *msg_ps;    u8_t req_idx;    /* 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)    {      err_t err_ret;      u16_t payload_len;      u16_t payload_ofs;      u16_t varbind_ofs = 0;      /* 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;      /* read UDP payload length from UDP header */      payload_len = ntohs(udphdr->len) - UDP_HLEN;      /* adjust to UDP payload */      payload_ofs = UDP_HLEN;      /* check total length, version, community, pdu type */      err_ret = snmp_pdu_header_check(p, payload_ofs, payload_len, &varbind_ofs, msg_ps);      if (((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)) )      {        /* Only accept requests and requests without error (be robust) */        err_ret = err_ret;      }      else      {        /* Reject response and trap headers or error requests as input! */        err_ret = ERR_ARG;      }      if (err_ret == ERR_OK)      {        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);        if ((err_ret == ERR_OK) && (msg_ps->invb.count > 0))        {          /* we've decoded the incoming message, release input msg now */          pbuf_free(p);          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);        }        else        {          /* varbind-list decode failed, or varbind list empty.             drop request silently, do not return error!             (errors are only returned for a specific varbind failure) */          pbuf_free(p);          LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_dec_varbindlist() failed\n"));        }      }      else      {        /* header check failed           drop request silently, do not return error! */        pbuf_free(p);        LWIP_DEBUGF(SNMP_MSG_DEBUG, ("snmp_pdu_header_check() failed\n"));      }    }    else    {      /* exceeding number of concurrent requests */      pbuf_free(p);    }  }  else  {    /* datagram not for us */    pbuf_free(p);  }}/** * 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;

⌨️ 快捷键说明

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