snmp_api.c
资源名称:snmp.src.rar [点击查看]
上传用户:cxs890
上传日期:2021-05-22
资源大小:347k
文件大小:144k
源码类别:
SNMP编程
开发平台:
C/C++
- DEBUGINDENTADD(-8);
- if (after_header != NULL)
- *length = tmp_buf_len;
- if (ret != SNMPERR_SUCCESS) {
- ERROR_MSG("error parsing PDU");
- snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
- return SNMPERR_ASN_PARSE_ERR;
- }
- return SNMPERR_SUCCESS;
- } /* end snmpv3_parse() */
- #define ERROR_STAT_LENGTH 11
- int
- snmpv3_make_report(struct snmp_pdu *pdu, int error)
- {
- long ltmp;
- static oid unknownSecurityLevel[] = {1,3,6,1,6,3,15,1,1,1,0};
- static oid notInTimeWindow[] = {1,3,6,1,6,3,15,1,1,2,0};
- static oid unknownUserName[] = {1,3,6,1,6,3,15,1,1,3,0};
- static oid unknownEngineID[] = {1,3,6,1,6,3,15,1,1,4,0};
- static oid wrongDigest[] = {1,3,6,1,6,3,15,1,1,5,0};
- static oid decryptionError[] = {1,3,6,1,6,3,15,1,1,6,0};
- oid *err_var;
- int err_var_len;
- int stat_ind;
- switch (error) {
- case SNMPERR_USM_UNKNOWNENGINEID:
- stat_ind = STAT_USMSTATSUNKNOWNENGINEIDS;
- err_var = unknownEngineID;
- err_var_len = ERROR_STAT_LENGTH;
- break;
- case SNMPERR_USM_UNKNOWNSECURITYNAME:
- stat_ind = STAT_USMSTATSUNKNOWNUSERNAMES;
- err_var = unknownUserName;
- err_var_len = ERROR_STAT_LENGTH;
- break;
- case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL:
- stat_ind = STAT_USMSTATSUNSUPPORTEDSECLEVELS;
- err_var = unknownSecurityLevel;
- err_var_len = ERROR_STAT_LENGTH;
- break;
- case SNMPERR_USM_AUTHENTICATIONFAILURE:
- stat_ind = STAT_USMSTATSWRONGDIGESTS;
- err_var = wrongDigest;
- err_var_len = ERROR_STAT_LENGTH;
- break;
- case SNMPERR_USM_NOTINTIMEWINDOW:
- stat_ind = STAT_USMSTATSNOTINTIMEWINDOWS;
- err_var = notInTimeWindow;
- err_var_len = ERROR_STAT_LENGTH;
- break;
- case SNMPERR_USM_DECRYPTIONERROR:
- stat_ind = STAT_USMSTATSDECRYPTIONERRORS;
- err_var = decryptionError;
- err_var_len = ERROR_STAT_LENGTH;
- break;
- default:
- return SNMPERR_GENERR;
- break;
- }
- snmp_free_varbind(pdu->variables); /* free the current varbind */
- pdu->variables = NULL;
- SNMP_FREE(pdu->securityEngineID);
- pdu->securityEngineID = snmpv3_generate_engineID(&pdu->securityEngineIDLen);
- SNMP_FREE(pdu->contextEngineID);
- pdu->contextEngineID = snmpv3_generate_engineID(&pdu->contextEngineIDLen);
- pdu->command = SNMP_MSG_REPORT;
- pdu->errstat = 0;
- pdu->errindex = 0;
- pdu->contextName = strdup("");
- pdu->contextNameLen = strlen(pdu->contextName);
- /* reports shouldn't cache previous data. */
- /* FIX - yes they should but USM needs to follow new EoP to determine
- which cached values to use
- */
- if (pdu->securityStateRef) {
- usm_free_usmStateReference(pdu->securityStateRef);
- pdu->securityStateRef = NULL;
- }
- if (error != SNMPERR_USM_NOTINTIMEWINDOW)
- pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
- else
- pdu->securityLevel = SNMP_SEC_LEVEL_AUTHNOPRIV;
- /* find the appropriate error counter
- */
- ltmp = snmp_get_statistic(stat_ind);
- /* return the appropriate error counter
- */
- snmp_pdu_add_variable(pdu, err_var, err_var_len,
- ASN_COUNTER, (u_char *) <mp, sizeof(ltmp));
- return SNMPERR_SUCCESS;
- } /* end snmpv3_make_report() */
- int
- snmpv3_get_report_type(struct snmp_pdu *pdu)
- {
- static oid snmpMPDStats[] = {1,3,6,1,6,3,11,2,1};
- static oid usmStats[] = {1,3,6,1,6,3,15,1,1};
- struct variable_list *vp;
- int rpt_type = SNMPERR_UNKNOWN_REPORT;
- if (pdu == NULL || pdu->variables == NULL) return rpt_type;
- vp = pdu->variables;
- if (vp->name_length == REPORT_STATS_LEN+2) {
- if (memcmp(snmpMPDStats,vp->name,REPORT_STATS_LEN*sizeof(oid)) == 0) {
- switch (vp->name[REPORT_STATS_LEN]) {
- case REPORT_snmpUnknownSecurityModels_NUM:
- rpt_type = SNMPERR_UNKNOWN_SEC_MODEL;
- break;
- case REPORT_snmpInvalidMsgs_NUM:
- rpt_type = SNMPERR_INVALID_MSG;
- break;
- }
- } else if (memcmp(usmStats,vp->name,REPORT_STATS_LEN*sizeof(oid)) == 0) {
- switch (vp->name[REPORT_STATS_LEN]) {
- case REPORT_usmStatsUnsupportedSecLevels_NUM:
- rpt_type = SNMPERR_UNSUPPORTED_SEC_LEVEL;
- break;
- case REPORT_usmStatsNotInTimeWindows_NUM:
- rpt_type = SNMPERR_NOT_IN_TIME_WINDOW;
- break;
- case REPORT_usmStatsUnknownUserNames_NUM:
- rpt_type = SNMPERR_UNKNOWN_USER_NAME;
- break;
- case REPORT_usmStatsUnknownEngineIDs_NUM:
- rpt_type = SNMPERR_UNKNOWN_ENG_ID;
- break;
- case REPORT_usmStatsWrongDigests_NUM:
- rpt_type = SNMPERR_AUTHENTICATION_FAILURE;
- break;
- case REPORT_usmStatsDecryptionErrors_NUM:
- rpt_type = SNMPERR_DECRYPTION_ERR;
- break;
- }
- }
- }
- DEBUGMSGTL(("report", "Report type: %dn", rpt_type));
- return rpt_type;
- }
- /*
- * Parses the packet received on the input session, and places the data into
- * the input pdu. length is the length of the input packet.
- * If any errors are encountered, -1 or USM error is returned.
- * Otherwise, a 0 is returned.
- */
- static int
- _snmp_parse(void * sessp,
- struct snmp_session *session,
- struct snmp_pdu *pdu,
- u_char *data,
- size_t length)
- {
- u_char community[COMMUNITY_MAX_LEN];
- size_t community_length = COMMUNITY_MAX_LEN;
- int result = -1;
- snmp_current_community = NULL;
- session->s_snmp_errno = 0;
- session->s_errno = 0;
- /* Ensure all incoming PDUs have a unique means of identification
- (This is not restricted to AgentX handling,
- though that is where the need becomes visible) */
- pdu->transid = snmp_get_next_transid();
- if (session->version != SNMP_DEFAULT_VERSION)
- pdu->version = session->version;
- else
- pdu->version = snmp_parse_version(data,length);
- switch (pdu->version) {
- case SNMP_VERSION_1:
- case SNMP_VERSION_2c:
- DEBUGMSGTL(("snmp_api","Parsing SNMPv%d message...n", (1 + pdu->version)));
- /* authenticates message and returns length if valid */
- DEBUGDUMPSETUP("dump_recv", data, 4);
- DEBUGMSG(("dump_recv", "SNMPv%d messagen", (1+pdu->version)));
- DEBUGINDENTMORE();
- data = snmp_comstr_parse(data, &length, community, &community_length, &pdu->version);
- DEBUGINDENTLESS();
- if (data == NULL)
- return -1;
- if (pdu->version != session->version &&
- session->version != SNMP_DEFAULT_VERSION)
- {
- session->s_snmp_errno = SNMPERR_BAD_VERSION;
- return -1;
- }
- /* maybe get the community string. */
- pdu->securityLevel = SNMP_SEC_LEVEL_NOAUTH;
- pdu->securityModel = (pdu->version == SNMP_VERSION_1) ?
- SNMP_SEC_MODEL_SNMPv1 : SNMP_SEC_MODEL_SNMPv2c;
- SNMP_FREE(pdu->community);
- pdu->community_len = 0;
- pdu->community = (u_char *)0;
- if (community_length) {
- pdu->community_len = community_length;
- snmp_current_community = pdu->community = (u_char *)malloc(community_length + 1);
- if (pdu->community == NULL)
- return -1;
- memmove(pdu->community, community, community_length);
- snmp_current_community[community_length] = 0;
- }
- if (session->authenticator){
- data = session->authenticator(data, &length,
- community,
- community_length);
- if (data == NULL)
- {
- session->s_snmp_errno = SNMPERR_AUTHENTICATION_FAILURE;
- return -1;
- }
- }
- result = snmp_pdu_parse(pdu, data, &length);
- if (result < 0)
- {
- snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
- }
- break;
- case SNMP_VERSION_3:
- result = snmpv3_parse(pdu, data, &length, NULL);
- DEBUGMSGTL(("snmp_parse",
- "Parsed SNMPv3 message (secName:%s, secLevel:%s): %sn",
- pdu->securityName, usmSecLevelName[pdu->securityLevel],
- snmp_api_errstring(result)));
- if (result) {
- if (!sessp)
- session->s_snmp_errno = result;
- else
- /* handle reportable errors */
- switch (result) {
- case SNMPERR_USM_UNKNOWNENGINEID:
- case SNMPERR_USM_UNKNOWNSECURITYNAME:
- case SNMPERR_USM_UNSUPPORTEDSECURITYLEVEL:
- case SNMPERR_USM_AUTHENTICATIONFAILURE:
- case SNMPERR_USM_NOTINTIMEWINDOW:
- case SNMPERR_USM_DECRYPTIONERROR:
- if (SNMP_CMD_CONFIRMED(pdu->command) ||
- (pdu->command == 0 &&
- (pdu->flags & SNMP_MSG_FLAG_RPRT_BIT ))) {
- struct snmp_pdu *pdu2;
- int flags = pdu->flags;
- pdu->flags |= UCD_MSG_FLAG_FORCE_PDU_COPY;
- pdu2 = snmp_clone_pdu(pdu);
- pdu->flags = pdu2->flags = flags;
- snmpv3_make_report(pdu2, result);
- snmp_sess_send(sessp, pdu2);
- }
- break;
- default:
- session->s_snmp_errno = result;
- break;
- }
- }
- break;
- case SNMPERR_BAD_VERSION:
- ERROR_MSG("error parsing snmp message version");
- snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
- session->s_snmp_errno = SNMPERR_BAD_VERSION;
- break;
- case SNMP_VERSION_sec:
- case SNMP_VERSION_2u:
- case SNMP_VERSION_2star:
- case SNMP_VERSION_2p:
- default:
- ERROR_MSG("unsupported snmp message version");
- snmp_increment_statistic(STAT_SNMPINBADVERSIONS);
- session->s_snmp_errno = SNMPERR_BAD_VERSION;
- break;
- }
- return result;
- }
- static int
- snmp_parse(void *sessp,
- struct snmp_session *pss,
- struct snmp_pdu *pdu,
- u_char *data,
- size_t length)
- {
- int rc;
- rc = _snmp_parse(sessp,pss,pdu,data,length);
- if (rc) {
- if ( !pss->s_snmp_errno)
- pss->s_snmp_errno = SNMPERR_BAD_PARSE;
- SET_SNMP_ERROR(pss->s_snmp_errno);
- }
- return rc;
- }
- int
- snmp_pdu_parse(struct snmp_pdu *pdu, u_char *data, size_t *length) {
- u_char type;
- u_char msg_type;
- u_char *var_val;
- int badtype;
- size_t len;
- size_t four;
- struct variable_list *vp = NULL;
- struct soaddr_in *pduIp = (struct soaddr_in *)&(pdu->agent_addr);
- oid objid[MAX_OID_LEN];
- badtype = 0;
- DEBUGINDENTMORE();
- DEBUGMSG(("dump_recv", "PDUn"));
- /* Get the PDU type */
- data = asn_parse_header(data, length, &msg_type);
- if (data == NULL)
- return -1;
- pdu->command = msg_type;
- pdu->flags &= (~UCD_MSG_FLAG_RESPONSE_PDU);
- /* get the fields in the PDU preceeding the variable-bindings sequence */
- switch (pdu->command) {
- case SNMP_MSG_TRAP:
- /* enterprise */
- pdu->enterprise_length = MAX_OID_LEN;
- data = asn_parse_objid(data, length, &type, objid,
- &pdu->enterprise_length);
- if (data == NULL)
- return -1;
- pdu->enterprise = (oid *)malloc(pdu->enterprise_length * sizeof(oid));
- if (pdu->enterprise == NULL)
- return -1;
- memmove(pdu->enterprise, objid, pdu->enterprise_length * sizeof(oid));
- /* agent-addr */
- four = 4;
- pduIp->sin_family = AF_INET;
- data = asn_parse_string(data, length, &type,
- (u_char *)&pduIp->sin_addr.s_addr,
- &four);
- if (data == NULL)
- return -1;
- /* generic trap */
- data = asn_parse_int(data, length, &type, (long *)&pdu->trap_type,
- sizeof(pdu->trap_type));
- if (data == NULL)
- return -1;
- /* specific trap */
- data = asn_parse_int(data, length, &type, (long *)&pdu->specific_type,
- sizeof(pdu->specific_type));
- if (data == NULL)
- return -1;
- /* timestamp */
- data = asn_parse_unsigned_int(data, length, &type, &pdu->time,
- sizeof(pdu->time));
- if (data == NULL)
- return -1;
- break;
- case SNMP_MSG_RESPONSE:
- case SNMP_MSG_REPORT:
- pdu->flags |= UCD_MSG_FLAG_RESPONSE_PDU;
- /* fallthrough */
- default:
- /* PDU is not an SNMPv1 TRAP */
- /* request id */
- DEBUGDUMPHEADER("dump_recv", "Parsing request_idn");
- data = asn_parse_int(data, length, &type, &pdu->reqid,
- sizeof(pdu->reqid));
- DEBUGINDENTLESS();
- if (data == NULL) {
- return -1;
- }
- /* error status (getbulk non-repeaters) */
- DEBUGDUMPHEADER("dump_recv", "Parsing error statusn");
- data = asn_parse_int(data, length, &type, &pdu->errstat,
- sizeof(pdu->errstat));
- DEBUGINDENTLESS();
- if (data == NULL) {
- return -1;
- }
- /* error index (getbulk max-repetitions) */
- DEBUGDUMPHEADER("dump_recv", "Parsing error indexn");
- data = asn_parse_int(data, length, &type, &pdu->errindex,
- sizeof(pdu->errindex));
- DEBUGINDENTLESS();
- if (data == NULL) {
- return -1;
- }
- }
- /* get header for variable-bindings sequence */
- DEBUGDUMPHEADER("dump_recv", "VarBindList:n");
- data = asn_parse_sequence(data, length, &type,
- (ASN_SEQUENCE | ASN_CONSTRUCTOR), "varbinds");
- if (data == NULL)
- return -1;
- /* get each varBind sequence */
- while((int)*length > 0){
- struct variable_list *vptemp;
- vptemp = (struct variable_list *)malloc(sizeof(*vptemp));
- if (0 == vptemp) {
- return -1;
- }
- if (0 == vp){
- pdu->variables = vptemp;
- } else {
- vp->next_variable = vptemp;
- }
- vp = vptemp;
- vp->next_variable = NULL;
- vp->val.string = NULL;
- vp->name_length = MAX_OID_LEN;
- vp->name = 0;
- DEBUGDUMPHEADER("dump_recv", "VarBind:n");
- data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type,
- &vp->val_len, &var_val, length);
- if (data == NULL)
- return -1;
- if (snmp_set_var_objid(vp, objid, vp->name_length))
- return -1;
- len = PACKET_LENGTH;
- switch((short)vp->type){
- case ASN_INTEGER:
- vp->val.integer = (long *)vp->buf;
- vp->val_len = sizeof(long);
- asn_parse_int(var_val, &len, &vp->type,
- (long *)vp->val.integer,
- sizeof(vp->val.integer));
- break;
- case ASN_COUNTER:
- case ASN_GAUGE:
- case ASN_TIMETICKS:
- case ASN_UINTEGER:
- vp->val.integer = (long *)vp->buf;
- vp->val_len = sizeof(u_long);
- asn_parse_unsigned_int(var_val, &len, &vp->type,
- (u_long *)vp->val.integer,
- sizeof(vp->val.integer));
- break;
- #ifdef OPAQUE_SPECIAL_TYPES
- case ASN_OPAQUE_COUNTER64:
- case ASN_OPAQUE_U64:
- #endif /* OPAQUE_SPECIAL_TYPES */
- case ASN_COUNTER64:
- vp->val.counter64 = (struct counter64 *)vp->buf;
- vp->val_len = sizeof(struct counter64);
- asn_parse_unsigned_int64(var_val, &len, &vp->type,
- (struct counter64 *)vp->val.counter64,
- sizeof(*vp->val.counter64));
- break;
- #ifdef OPAQUE_SPECIAL_TYPES
- case ASN_OPAQUE_FLOAT:
- vp->val.floatVal = (float *)vp->buf;
- vp->val_len = sizeof(float);
- asn_parse_float(var_val, &len, &vp->type,
- vp->val.floatVal,
- vp->val_len);
- break;
- case ASN_OPAQUE_DOUBLE:
- vp->val.doubleVal = (double *)vp->buf;
- vp->val_len = sizeof(double);
- asn_parse_double(var_val, &len, &vp->type,
- vp->val.doubleVal,
- vp->val_len);
- break;
- case ASN_OPAQUE_I64:
- vp->val.counter64 = (struct counter64 *)vp->buf;
- vp->val_len = sizeof(struct counter64);
- asn_parse_signed_int64(var_val, &len, &vp->type,
- (struct counter64 *)vp->val.counter64,
- sizeof(*vp->val.counter64));
- break;
- #endif /* OPAQUE_SPECIAL_TYPES */
- case ASN_OCTET_STR:
- case ASN_IPADDRESS:
- case ASN_OPAQUE:
- case ASN_NSAP:
- if (vp->val_len < sizeof(vp->buf)){
- vp->val.string = (u_char *)vp->buf;
- } else {
- vp->val.string = (u_char *)malloc((unsigned)vp->val_len);
- if (vp->val.string == NULL)
- return -1;
- }
- asn_parse_string(var_val, &len, &vp->type, vp->val.string,
- &vp->val_len);
- break;
- case ASN_OBJECT_ID:
- vp->val_len = MAX_OID_LEN;
- asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len);
- vp->val_len *= sizeof(oid);
- vp->val.objid = (oid *)malloc((unsigned)vp->val_len);
- if (vp->val.objid == NULL)
- return -1;
- memmove(vp->val.objid, objid, vp->val_len);
- break;
- case SNMP_NOSUCHOBJECT:
- case SNMP_NOSUCHINSTANCE:
- case SNMP_ENDOFMIBVIEW:
- case ASN_NULL:
- break;
- case ASN_BIT_STR:
- vp->val.bitstring = (u_char *)malloc(vp->val_len);
- if (vp->val.bitstring == NULL)
- return -1;
- asn_parse_bitstring(var_val, &len, &vp->type,
- vp->val.bitstring, &vp->val_len);
- break;
- default:
- snmp_log(LOG_ERR,"bad type returned (%x)n", vp->type);
- badtype = 1;
- break;
- }
- DEBUGINDENTLESS();
- }
- DEBUGINDENTLESS();
- DEBUGINDENTLESS();
- return badtype;
- }
- /* snmp v3 utility function to parse into the scopedPdu. stores contextName
- and contextEngineID in pdu struct. Also stores pdu->command (handy for
- Report generation).
- returns pointer to begining of PDU or NULL on error.
- */
- u_char *
- snmpv3_scopedPDU_parse(struct snmp_pdu *pdu,
- u_char *cp,
- size_t *length)
- {
- u_char tmp_buf[SNMP_MAX_MSG_SIZE];
- size_t tmp_buf_len;
- u_char type;
- size_t asn_len;
- u_char* data;
- pdu->command = 0; /* initialize so we know if it got parsed */
- asn_len = *length;
- data = asn_parse_sequence(cp, &asn_len, &type,
- (ASN_SEQUENCE | ASN_CONSTRUCTOR), "plaintext scopedPDU");
- if (data == NULL){
- return NULL;
- }
- *length -= data - cp;
- /* contextEngineID from scopedPdu */
- DEBUGDUMPHEADER("dump_recv", "Parsing contextEngineIDn");
- data = asn_parse_string(data, length, &type, pdu->contextEngineID,
- &pdu->contextEngineIDLen);
- DEBUGINDENTLESS();
- if (data == NULL) {
- ERROR_MSG("error parsing contextEngineID from scopedPdu");
- return NULL;
- }
- /* check that it agrees with engineID returned from USM above
- * only a warning because this could be legal if we are a proxy
- */
- if (pdu->securityEngineIDLen != pdu->contextEngineIDLen ||
- memcmp(pdu->securityEngineID, pdu->contextEngineID,
- pdu->securityEngineIDLen) != 0) {
- DEBUGMSGTL(("scopedPDU_parse",
- "inconsistent engineID information in messagen"));
- }
- /* parse contextName from scopedPdu
- */
- tmp_buf_len = SNMP_MAX_CONTEXT_SIZE;
- DEBUGDUMPHEADER("dump_recv", "Parsing contextNamen");
- data = asn_parse_string(data, length, &type, tmp_buf, &tmp_buf_len);
- DEBUGINDENTLESS();
- if (data == NULL) {
- ERROR_MSG("error parsing contextName from scopedPdu");
- return NULL;
- }
- if (tmp_buf_len) {
- pdu->contextName = (char *)malloc(tmp_buf_len);
- if (pdu->contextName == NULL)
- return NULL;
- memmove(pdu->contextName, tmp_buf, tmp_buf_len);
- pdu->contextNameLen = tmp_buf_len;
- } else {
- pdu->contextName = strdup("");
- if (pdu->contextName == NULL)
- return NULL;
- pdu->contextNameLen = 0;
- }
- /* Get the PDU type */
- asn_len = *length;
- DEBUGDUMPHEADER("dump_recv", "Parsing PDU typen");
- cp = asn_parse_header(data, &asn_len, &type);
- DEBUGINDENTLESS();
- if (cp == NULL)
- return NULL;
- pdu->command = type;
- return data;
- }
- /*
- * Sends the input pdu on the session after calling snmp_build to create
- * a serialized packet. If necessary, set some of the pdu data from the
- * session defaults. Add a request corresponding to this pdu to the list
- * of outstanding requests on this session, then send the pdu.
- * Returns the request id of the generated packet if applicable, otherwise 1.
- * On any error, 0 is returned.
- * The pdu is freed by snmp_send() unless a failure occured.
- */
- int
- snmp_send(struct snmp_session *session,
- struct snmp_pdu *pdu)
- {
- return snmp_async_send(session, pdu, NULL, NULL);
- }
- int
- snmp_sess_send(void *sessp,
- struct snmp_pdu *pdu)
- {
- return snmp_sess_async_send(sessp, pdu, NULL, NULL);
- }
- /*
- * int snmp_async_send(session, pdu, callback, cb_data)
- * struct snmp_session *session;
- * struct snmp_pdu *pdu;
- * snmp_callback callback;
- * void *cb_data;
- *
- * Sends the input pdu on the session after calling snmp_build to create
- * a serialized packet. If necessary, set some of the pdu data from the
- * session defaults. Add a request corresponding to this pdu to the list
- * of outstanding requests on this session and store callback and data,
- * then send the pdu.
- * Returns the request id of the generated packet if applicable, otherwise 0.
- * On any error, 0 is returned.
- * The pdu is freed by snmp_send() unless a failure occurred.
- */
- int
- snmp_async_send(struct snmp_session *session,
- struct snmp_pdu *pdu,
- snmp_callback callback,
- void *cb_data)
- {
- void *sessp = snmp_sess_pointer(session);
- return snmp_sess_async_send(sessp, pdu, callback, cb_data);
- }
- static int
- _sess_async_send(void *sessp,
- struct snmp_pdu *pdu,
- snmp_callback callback,
- void *cb_data)
- {
- struct session_list *slp = (struct session_list *)sessp;
- struct snmp_session *session;
- struct snmp_internal_session *isp;
- u_char *packet;
- size_t length = PACKET_LENGTH;
- struct soaddr_in *isp_addr;
- struct soaddr_in *pduIp;
- int result, addr_size;
- long reqid;
- packet = packet_buffer_read;
- session = slp->session; isp = slp->internal;
- if (!session || !isp) {
- DEBUGMSGTL(("sess_read","send fail: closing...n"));
- return 0;
- }
- session->s_snmp_errno = 0;
- session->s_errno = 0;
- if (pdu == NULL) {
- session->s_snmp_errno = SNMPERR_NULL_PDU;
- return 0;
- }
- #if TEMPORARILY_DISABLED
- /*
- * NULL variable are allowed in certain PDU types.
- * In particular, SNMPv3 engineID probes are of this form.
- * There is an internal PDU flag to indicate that this
- * is acceptable, but until the construction of engineID
- * probes can be amended to set this flag, we'll simply
- * skip this test altogether.
- */
- if (pdu->variables == NULL) {
- switch (pdu->command) {
- case SNMP_MSG_GET:
- case SNMP_MSG_SET:
- case SNMP_MSG_GETNEXT:
- case SNMP_MSG_GETBULK:
- case SNMP_MSG_RESPONSE:
- case SNMP_MSG_TRAP2:
- case SNMP_MSG_REPORT:
- case SNMP_MSG_INFORM:
- session->s_snmp_errno = snmp_errno = SNMPERR_NO_VARS;
- return 0;
- case SNMP_MSG_TRAP:
- break;
- }
- }
- #endif
- pduIp = (struct soaddr_in *)&(pdu->address);
- pdu->flags |= UCD_MSG_FLAG_EXPECT_RESPONSE;
- /* check/setup the version */
- if (pdu->version == SNMP_DEFAULT_VERSION) {
- if (session->version == SNMP_DEFAULT_VERSION) {
- session->s_snmp_errno = SNMPERR_BAD_VERSION;
- return 0;
- }
- pdu->version = session->version;
- } else if (session->version == SNMP_DEFAULT_VERSION) {
- /* It's OK */
- } else if (pdu->version != session->version) {
- /* ENHANCE: we should support multi-lingual sessions */
- session->s_snmp_errno = SNMPERR_BAD_VERSION;
- return 0;
- }
- if (pdu->address.sa_family == AF_UNSPEC){
- isp_addr = (struct soaddr_in *)&(isp->addr);
- if (isp->addr.sa_family == AF_UNSPEC ||
- (isp->addr.sa_family == AF_INET &&
- isp_addr->sin_addr.s_addr == SNMP_DEFAULT_ADDRESS)){
- session->s_snmp_errno = SNMPERR_BAD_ADDRESS;
- return 0;
- }
- memmove(&pdu->address, &(isp->addr), sizeof(isp->addr));
- }
- addr_size = snmp_socket_length(pdu->address.sa_family);
- /* build the message to send */
- if (isp->hook_build)
- result = isp->hook_build(session, pdu, packet, &length);
- else
- result = snmp_build(session, pdu, packet, &length);
- if (result < 0){
- return 0;
- }
- /*
- *if the packet size is larger than the local constraint
- *of maximum message size, act as defined in RFC 1905.
- * --sxf 2000-1-4
- */
- if (length > snmp_para.packetsize)
- {
- snmp_log (LOG_ERR, "Out packet to bign");
- snmp_increment_statistic(STAT_SNMPOUTTOOBIGS);
- snmp_increment_statistic(STAT_SNMPSILENTDROPS);
- snmp_free_varbind (pdu->variables);
- pdu->variables = NULL;
- pdu->errstat = SNMP_ERR_TOOBIG;
- pdu->errindex = 0;
- if (isp->hook_build)
- result = isp->hook_build(session, pdu, packet, &length);
- else
- result = snmp_build(session, pdu, packet, &length);
- if (result < 0){
- return 0;
- }
- /*
- *The pdu's type is response pdu, we don't know if it is the from getbulk request.
- *May be it should be processed earlier;
- */
- /*
- else
- {
- int count, i;
- struct variable_list *vptr;
- VARIABLE_CUT_RETRY:
- count = 0;
- for (vptr = pdu->variables; vptr != NULL; vptr = vptr->next_variable)
- count++;
- if (count > 0)
- {
- vptr = pdu->variables;
- for (i = 0; i < count/2; i++)
- {
- vptr = vptr->next_variable;
- }
- if (vptr != NULL)
- {
- snmp_free_varbind (vptr->next_variable);
- vptr->next_variable = NULL;
- }
- if (isp->hook_build)
- result = isp->hook_build(session, pdu, packet, &length);
- else
- result = snmp_build(session, pdu, packet, &length);
- if (result < 0){
- return 0;
- }
- if (length > snmp_para.packetsize)
- goto VARIABLE_CUT_RETRY;
- }
- else
- {
- pdu->errstat = SNMPERR_TOO_LONG;
- pdu->errindex = 0;
- if (isp->hook_build)
- result = isp->hook_build(session, pdu, packet, &length);
- else
- result = snmp_build(session, pdu, packet, &length);
- if (result < 0){
- return 0;
- }
- }
- }/*end of if (pdu->command != SNMP_MSG_GETBULK)*/
- }
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET)){
- snmp_log(LOG_DEBUG, "nSending %u bytes to %s:%hun", length,
- inet_ntoa(pduIp->sin_addr), ntohs(pduIp->sin_port));
- xdump(packet, length, "");
- }
- /* send the message */
- /*fanghao(A):2005-06-17*/
- #ifndef SWITCH
- if(session->vrfname[0]){
- if(so_bind_udp_vrf_byname(isp->sd, session->vrfname,0) < 0){
- session->s_snmp_errno = SNMPERR_BIND_VRF;
- session->s_errno = errno;
- return 0;
- }
- }else if(session->vrfid !=0){
- if( so_bind_udp_vrf_byid(isp->sd, (unsigned long)session->vrfid, 0) ){
- session->s_snmp_errno = SNMPERR_BIND_VRF;
- session->s_errno = errno;
- return 0;
- }
- }
- #endif
- result = so_sendto(isp->sd, (char *)packet, length, 0,
- (struct soaddr *)&pdu->address, addr_size);
- #ifndef SWITCH
- /*fanghao(A):2005-06-17*/
- addr_size = snmp_socket_length(isp->me.sa_family);
- if (udp_bind_localaddr(isp->sd, (struct soaddr *)&isp->me, addr_size) != 0){
- session->s_snmp_errno = SNMPERR_BAD_LOCPORT;
- session->s_errno = errno;
- snmp_set_detail(strerror(errno));
- snmp_sess_close(slp);
- return 0;
- }
- #endif
- if ( result < 0){
- session->s_snmp_errno = SNMPERR_BAD_SENDTO;
- session->s_errno = errno;
- return 0;
- }
- reqid = pdu->reqid;
- /* add to pending requests list if expect a response */
- if (pdu->flags & UCD_MSG_FLAG_EXPECT_RESPONSE) {
- struct request_list *rp;
- struct timeval tv;
- rp = (struct request_list *)calloc( 1, sizeof(struct request_list));
- if (rp == NULL) {
- session->s_snmp_errno = SNMPERR_GENERR;
- return 0;
- }
- gettimeofday(&tv, (struct timezone *)0);
- rp->pdu = pdu;
- rp->request_id = pdu->reqid;
- rp->message_id = pdu->msgid;
- rp->callback = callback;
- rp->cb_data = cb_data;
- rp->retries = 0;
- rp->timeout = session->timeout;
- rp->time = tv;
- tv.tv_usec += rp->timeout;
- tv.tv_sec += tv.tv_usec / 1000000L;
- tv.tv_usec %= 1000000L;
- rp->expire = tv;
- /* XX lock should be per session ! */
- snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
- if (isp->requestsEnd){
- rp->next_request = isp->requestsEnd->next_request;
- isp->requestsEnd->next_request = rp;
- isp->requestsEnd = rp;
- } else {
- rp->next_request = isp->requests;
- isp->requests = rp;
- isp->requestsEnd = rp;
- }
- snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
- }
- else
- snmp_free_pdu(pdu); /* free v1 or v2 TRAP PDU */
- if (reqid == 0) {
- syslog(LOG_WARNING, "SNMP-%d-ZEROREQID: Received snmp pdu with request id 0n", LOG_WARNING);
- reqid = 1;
- }
- return reqid;
- }
- int
- snmp_sess_async_send(void *sessp,
- struct snmp_pdu *pdu,
- snmp_callback callback,
- void *cb_data)
- {
- int rc;
- if (sessp == NULL){
- snmp_errno = SNMPERR_BAD_SESSION; /*MTCRITICAL_RESOURCE*/
- return(0);
- }
- rc = _sess_async_send(sessp,pdu,callback,cb_data);
- if (rc == 0) {
- struct session_list *psl;
- struct snmp_session *pss;
- psl = (struct session_list *)sessp;
- pss = psl->session;
- SET_SNMP_ERROR(pss->s_snmp_errno);
- }
- return rc;
- }
- /*
- * Frees the variable and any malloc'd data associated with it.
- */
- void
- snmp_free_var(struct variable_list *var)
- {
- if (!var) return;
- if (var->name != var->name_loc)
- SNMP_FREE(var->name);
- if (var->val.string != var->buf)
- SNMP_FREE(var->val.string);
- free(var);
- }
- void snmp_free_varbind(struct variable_list *var)
- {
- struct variable_list *ptr;
- while(var) {
- ptr = var->next_variable;
- snmp_free_var(var);
- var = ptr;
- }
- }
- /*
- * Frees the pdu and any malloc'd data associated with it.
- */
- void
- snmp_free_pdu(struct snmp_pdu *pdu)
- {
- if (!pdu) return;
- snmp_free_varbind(pdu->variables);
- SNMP_FREE(pdu->enterprise);
- SNMP_FREE(pdu->community);
- SNMP_FREE(pdu->contextEngineID);
- SNMP_FREE(pdu->securityEngineID);
- SNMP_FREE(pdu->contextName);
- SNMP_FREE(pdu->securityName);
- free(pdu);
- }
- /*
- * Checks to see if any of the fd's set in the fdset belong to
- * snmp. Each socket with it's fd set has a packet read from it
- * and snmp_parse is called on the packet received. The resulting pdu
- * is passed to the callback routine for that session. If the callback
- * routine returns successfully, the pdu and it's request are deleted.
- */
- void
- snmp_read(fd_set *fdset)
- {
- struct session_list *slp;
- snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
- for(slp = Sessions; slp; slp = slp->next){
- snmp_sess_read((void *)slp, fdset);
- }
- snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
- }
- #ifdef INCLUDE_BCMP
- extern uint32 bcmp_snmp_check_packet(struct snmp_session *session, struct snmp_pdu *pdu);
- #endif
- /* Same as snmp_read, but works just one session. */
- /* returns 0 if success, -1 if fail */
- /* MTR: can't lock here and at snmp_read */
- /* Beware recursive send maybe inside snmp_read callback function. */
- int
- _sess_read(void *sessp,
- fd_set *fdset)
- {
- struct session_list *slp = (struct session_list *)sessp;
- struct snmp_session *sp;
- struct snmp_internal_session *isp;
- u_char *packet, *packetptr ;
- /* u_char *ucp = 0;*/
- struct soaddr from;
- struct soaddr_in *fromIp = (struct soaddr_in *)&from;
- int length = 0;
- struct snmp_pdu *pdu;
- struct request_list *rp, *orp = NULL;
- int ret;
- /* int addrlen;*/
- int fromlength;
- packetptr = packet = packet_buffer_read;
- sp = slp->session; isp = slp->internal;
- if (!sp || !isp) {
- DEBUGMSGTL(("sess_read","read fail: closing...n"));
- return 0;
- }
- if ((!isp->newpkt && !(FD_ISSET(isp->sd, fdset)))) {
- DEBUGMSGTL(("sess_read","not reading...n"));
- return 0;
- }
- sp->s_snmp_errno = 0;
- sp->s_errno = 0;
- memset(&from, 0, sizeof(from));
- fromlength = sizeof(from);
- {
- length = so_recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0,
- (struct soaddr *)&from, &fromlength);
- if (from.sa_family == AF_UNSPEC)
- from.sa_family = AF_INET; /* bad bad bad OS, no bone! */
- /*fanghao(A):2005-06-17*/
- if( -1 != length )
- {
- struct soaddr_intf *pf;
- pf = (struct soaddr_intf *)&from;
- sp->vrfid = (uint32 )pf->sin_vrfid;
- }
- }
- if (length == -1) {
- sp->s_snmp_errno = SNMPERR_BAD_RECVFROM;
- sp->s_errno = errno;
- snmp_set_detail(strerror(errno));
- return -1;
- }
- if (length > snmp_para.packetsize)
- {
- sp->s_snmp_errno = SNMPERR_BAD_RECVFROM;
- snmp_increment_statistic (STAT_SNMPINTOOBIGS);
- snmp_log (LOG_ERR, "In packet to bign");
- return -1;
- }
- /* Remote end closed connection */
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET)){
- snmp_log(LOG_DEBUG, "nReceived %d bytes from %s:%hun", length,
- inet_ntoa(fromIp->sin_addr), ntohs(fromIp->sin_port));
- xdump(packetptr, length, "");
- }
- if ( isp->hook_pre ) {
- if ( isp->hook_pre( sp, from ) == 0 )
- {
- return -1;
- }
- }
- pdu = (struct snmp_pdu *)malloc(sizeof(struct snmp_pdu));
- if (pdu == NULL)
- return -1;
- memset (pdu, 0, sizeof(*pdu));
- pdu->address = from;
- pdu->available_community = 0;
- if ( isp->hook_parse )
- ret = isp->hook_parse(sp, pdu, packetptr, length);
- else
- ret = snmp_parse(sessp, sp, pdu, packetptr, length);
- if ( isp->hook_post ) {
- if ( isp->hook_post( sp, pdu, ret ) == 0 ) {
- snmp_free_pdu(pdu);
- return -1;
- }
- }
- if (ret != SNMP_ERR_NOERROR) {
- snmp_free_pdu(pdu);
- return -1;
- }
- #ifdef INCLUDE_BCMP
- if (bcmp_snmp_check_packet(sp, pdu) == SYS_ERROR)
- /*packet has been forwarded*/
- {
- return 0;
- }
- #endif
- if (pdu->flags & UCD_MSG_FLAG_RESPONSE_PDU) {
- /* call USM to free any securityStateRef supplied with the message */
- if (pdu->securityStateRef) {
- usm_free_usmStateReference(pdu->securityStateRef);
- pdu->securityStateRef = NULL;
- }
- for(rp = isp->requests; rp; orp = rp, rp = rp->next_request) {
- snmp_callback callback;
- void *magic;
- if (pdu->version == SNMP_VERSION_3) {
- /* msgId must match for V3 messages */
- if (rp->message_id != pdu->msgid) continue;
- /* check that message fields match original,
- * if not, no further processing */
- if (!snmpv3_verify_msg(rp,pdu)) break;
- } else {
- if (rp->request_id != pdu->reqid) continue;
- }
- if (rp->callback) {
- callback = rp->callback;
- magic = rp->cb_data;
- } else {
- callback = sp->callback;
- magic = sp->callback_magic;
- }
- /* MTR snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); ?* XX lock should be per session ! */
- if (callback == NULL ||
- callback(RECEIVED_MESSAGE,sp,pdu->reqid,pdu,magic) == 1){
- if (pdu->command == SNMP_MSG_REPORT) {
- if (sp->s_snmp_errno == SNMPERR_NOT_IN_TIME_WINDOW) {
- /* trigger immediate retry on recoverable Reports
- * (notInTimeWindow), incr_retries == TRUE to prevent
- * inifinite resend */
- if (rp->retries <= sp->retries) {
- snmp_resend_request(slp, rp, TRUE);
- break;
- }
- } else {
- if (SNMPV3_IGNORE_UNAUTH_REPORTS) break;
- }
- /* handle engineID discovery - */
- if (!sp->securityEngineIDLen && pdu->securityEngineIDLen) {
- sp->securityEngineID = (u_char *)malloc(pdu->securityEngineIDLen);
- if (sp->securityEngineID == NULL)
- {
- snmp_free_pdu(pdu);
- return -1;
- }
- memcpy(sp->securityEngineID, pdu->securityEngineID,
- pdu->securityEngineIDLen);
- sp->securityEngineIDLen = pdu->securityEngineIDLen;
- if (!sp->contextEngineIDLen) {
- sp->contextEngineID = (u_char *)malloc(pdu->securityEngineIDLen);
- if (sp->contextEngineID == NULL)
- {
- snmp_free_pdu(pdu);
- return -1;
- }
- memcpy(sp->contextEngineID, pdu->securityEngineID,
- pdu->securityEngineIDLen);
- sp->contextEngineIDLen = pdu->securityEngineIDLen;
- }
- }
- }
- /* successful, so delete request */
- if (isp->requests == rp){
- /* first in list */
- isp->requests = rp->next_request;
- if (isp->requestsEnd == rp)
- isp->requestsEnd = NULL;
- } else {
- orp->next_request = rp->next_request;
- if (isp->requestsEnd == rp)
- isp->requestsEnd = orp;
- }
- snmp_free_pdu(rp->pdu);
- free(rp);
- /* there shouldn't be any more requests with the
- same reqid */
- break;
- }
- /* MTR snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); ?* XX lock should be per session ! */
- }
- } else {
- if (sp->callback)
- {
- /* MTR snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION); */
- sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu,
- sp->callback_magic);
- /* MTR snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION); */
- }
- }
- /* call USM to free any securityStateRef supplied with the message */
- if (pdu->securityStateRef && pdu->command == SNMP_MSG_TRAP2) {
- usm_free_usmStateReference(pdu->securityStateRef);
- pdu->securityStateRef = NULL;
- }
- snmp_current_community = NULL;
- snmp_free_pdu(pdu);
- return 0;
- }
- /* returns 0 if success, -1 if fail */
- int
- snmp_sess_read(void *sessp,
- fd_set *fdset)
- {
- struct session_list *psl;
- struct snmp_session *pss;
- int rc;
- rc = _sess_read(sessp, fdset);
- psl = (struct session_list *)sessp;
- pss = psl->session;
- if (rc && pss->s_snmp_errno) {
- SET_SNMP_ERROR(pss->s_snmp_errno);
- }
- return rc;
- }
- /*
- *Trap use the same session list, so record the session list that is
- *not created by trap. --sxf 2k-12-27
- */
- void set_trapd_session_ptr (void)
- {
- trapdSessionPtr = (void*)Sessions;
- }
- /*
- * Returns info about what snmp requires from a select statement.
- * numfds is the number of fds in the list that are significant.
- * All file descriptors opened for SNMP are OR'd into the fdset.
- * If activity occurs on any of these file descriptors, snmp_read
- * should be called with that file descriptor set
- *
- * The timeout is the latest time that SNMP can wait for a timeout. The
- * select should be done with the minimum time between timeout and any other
- * timeouts necessary. This should be checked upon each invocation of select.
- * If a timeout is received, snmp_timeout should be called to check if the
- * timeout was for SNMP. (snmp_timeout is idempotent)
- *
- * The value of block indicates how the timeout value is interpreted.
- * If block is true on input, the timeout value will be treated as undefined,
- * but it must be available for setting in snmp_select_info. On return,
- * block is set to true if the value returned for timeout is undefined;
- * when block is set to false, timeout may be used as a parmeter to 'select'.
- *
- * snmp_select_info returns the number of open sockets. (i.e. The number of
- * sessions open)
- */
- int
- snmp_select_info(int *numfds,
- fd_set *fdset,
- struct timeval *timeout,
- int *block)
- /* input: set to 1 if input timeout value is undefined */
- /* set to 0 if input timeout value is defined */
- /* output: set to 1 if output timeout value is undefined */
- /* set to 0 if output rimeout vlaue id defined */
- {
- return snmp_sess_select_info((void *)trapdSessionPtr, numfds, fdset, timeout, block);
- }
- #define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
- /* Same as snmp_select_info, but works just one session. */
- int
- snmp_sess_select_info(void *sessp,
- int *numfds,
- fd_set *fdset,
- struct timeval *timeout,
- int *block)
- {
- struct session_list *slptest = (struct session_list *)sessp;
- struct session_list *slp, *next=NULL, *prev=NULL;
- struct snmp_internal_session *isp;
- struct request_list *rp;
- struct timeval now, earliest;
- int timer_set = 0;
- int active = 0, requests = 0;
- int next_alarm = 0;
- timerclear(&earliest);
- /*
- * For each request outstanding, add it's socket to the fdset,
- * and if it is the earliest timeout to expire, mark it as lowest.
- * If a single session is specified, do just for that session.
- */
- if (sessp) slp = slptest; else slp = Sessions;
- for(; slp; slp = next){
- isp = slp->internal;
- if (!isp) {
- DEBUGMSGTL(("sess_select","select fail: closing...n"));
- continue; /* close in progress - skip this one */
- }
- if (isp->sd == -1) {
- if (sessp == NULL) {
- /* This session was marked for deletion */
- if ( prev == NULL )
- Sessions = slp->next;
- else
- prev->next = slp->next;
- next = slp->next;
- }
- snmp_sess_close( slp );
- continue;
- }
- if ((isp->sd + 1) > *numfds)
- *numfds = (isp->sd + 1);
- FD_SET(isp->sd, fdset);
- if (isp->requests){
- /* found another session with outstanding requests */
- requests++;
- for(rp = isp->requests; rp; rp = rp->next_request){
- if ((!timerisset(&earliest)
- || (timercmp(&rp->expire, &earliest, <))))
- earliest = rp->expire;
- }
- }
- if (isp->newpkt) {
- /* don't block at all, more data waiting to be processed */
- DEBUGMSGTL(("sess_select","more data in buffer, not blockingn"));
- requests++;
- timer_set = 1;
- *block = 0;
- }
- active++;
- if (slp == slptest) break;
- prev = slp;
- next = slp->next;
- }
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_ALARM_DONT_USE_SIG)) {
- next_alarm = get_next_alarm_delay_time();
- }
- if (next_alarm == 0 && requests == 0) { /* if none are active, skip arithmetic */
- *block = 1; /* can block - timeout value is undefined if no requests*/
- return active;
- }
- /*
- * Now find out how much time until the earliest timeout. This
- * transforms earliest from an absolute time into a delta time, the
- * time left until the select should timeout.
- */
- gettimeofday(&now,(struct timezone *)0);
- /*Now = now;*/
- if (next_alarm != 0 && earliest.tv_sec > next_alarm) {
- earliest.tv_sec = next_alarm;
- earliest.tv_usec = 0;
- }
- if (timer_set || earliest.tv_sec < now.tv_sec) {
- earliest.tv_sec = 0;
- earliest.tv_usec = 100;
- }
- else if (earliest.tv_sec == now.tv_sec) {
- earliest.tv_sec = 0;
- earliest.tv_usec = (earliest.tv_usec - now.tv_usec);
- if (earliest.tv_usec < 0) {
- earliest.tv_usec = 100;
- }
- }
- else {
- earliest.tv_sec = (earliest.tv_sec - now.tv_sec);
- earliest.tv_usec = (earliest.tv_usec - now.tv_usec);
- if (earliest.tv_usec < 0) {
- earliest.tv_sec --;
- earliest.tv_usec = (1000000L + earliest.tv_usec);
- }
- }
- /* if it was blocking before or our delta time is less, reset timeout */
- if ((*block || (timercmp(&earliest, timeout, <)))){
- *timeout = earliest;
- *block = 0;
- }
- return active;
- }
- /*
- * snmp_timeout should be called whenever the timeout from snmp_select_info
- * expires, but it is idempotent, so snmp_timeout can be polled (probably a
- * cpu expensive proposition). snmp_timeout checks to see if any of the
- * sessions have an outstanding request that has timed out. If it finds one
- * (or more), and that pdu has more retries available, a new packet is formed
- * from the pdu and is resent. If there are no more retries available, the
- * callback for the session is used to alert the user of the timeout.
- */
- void
- snmp_timeout (void)
- {
- struct session_list *slp;
- snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
- for(slp = Sessions; slp; slp = slp->next){
- snmp_sess_timeout((void *)slp);
- }
- snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
- }
- static int
- snmp_resend_request(struct session_list *slp, struct request_list *rp,
- int incr_retries)
- {
- u_char packet[PACKET_LENGTH];
- size_t length = PACKET_LENGTH;
- struct timeval tv;
- struct snmp_session *sp;
- struct snmp_internal_session *isp;
- struct timeval now;
- int result, addr_size;
- sp = slp->session; isp = slp->internal;
- if (!sp || !isp) {
- DEBUGMSGTL(("sess_read","resend fail: closing...n"));
- return 0;
- }
- if (incr_retries) rp->retries++;
- /* always increment msgId for resent messages */
- rp->pdu->msgid = rp->message_id = snmp_get_next_msgid();
- /* retransmit this pdu */
- if (snmp_build(sp, rp->pdu, packet, &length) < 0){
- /* this should never happen */
- return -1;
- }
- if (ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET)){
- struct soaddr_in *pduIp;
- pduIp = (struct soaddr_in *)&(rp->pdu->address);
- snmp_log(LOG_DEBUG, "nResending %d bytes to %s:%hun", length,
- inet_ntoa(pduIp->sin_addr), ntohs(pduIp->sin_port));
- xdump(packet, length, "");
- }
- addr_size = snmp_socket_length(rp->pdu->address.sa_family);
- /*fanghao(A):2005-06-17*/
- #ifndef SWITCH
- if(sp->vrfname[0]){
- if(so_bind_udp_vrf_byname(isp->sd,sp->vrfname,0) < 0){
- sp->s_snmp_errno = SNMPERR_BIND_VRF;
- sp->s_errno = errno;
- return 0;
- }
- }else if(sp->vrfid !=0){
- if( so_bind_udp_vrf_byid(isp->sd, (unsigned long)sp->vrfid, 0) ){
- sp->s_snmp_errno = SNMPERR_BIND_VRF;
- sp->s_errno = errno;
- return 0;
- }
- }
- #endif
- result = so_sendto(isp->sd, (char *)packet, length, 0,
- (struct soaddr *)&rp->pdu->address, addr_size);
- /*fanghao(A):2005-06-17*/
- #ifndef SWITCH
- addr_size = snmp_socket_length(isp->me.sa_family);
- if (udp_bind_localaddr(isp->sd, (struct soaddr *)&isp->me, addr_size) != 0){
- sp->s_snmp_errno = SNMPERR_BAD_LOCPORT;
- sp->s_errno = errno;
- snmp_set_detail(strerror(errno));
- snmp_sess_close(slp);
- return 0;
- }
- #endif
- if ( result < 0){
- sp->s_snmp_errno = SNMPERR_BAD_SENDTO;
- sp->s_errno = errno;
- snmp_set_detail(strerror(errno));
- return -1;
- }
- else {
- gettimeofday(&now, (struct timezone *)0);
- tv = now;
- rp->time = tv;
- tv.tv_usec += rp->timeout;
- tv.tv_sec += tv.tv_usec / 1000000L;
- tv.tv_usec %= 1000000L;
- rp->expire = tv;
- }
- return 0;
- }
- void
- snmp_sess_timeout(void *sessp)
- {
- struct session_list *slp = (struct session_list*)sessp;
- struct snmp_session *sp;
- struct snmp_internal_session *isp;
- struct request_list *rp, *orp = NULL, *freeme = NULL;
- struct timeval now;
- snmp_callback callback;
- void *magic;
- sp = slp->session; isp = slp->internal;
- if (!sp || !isp) {
- DEBUGMSGTL(("sess_read","timeout fail: closing...n"));
- return;
- }
- gettimeofday(&now,(struct timezone *)0);
- /*
- * For each request outstanding, check to see if it has expired.
- */
- for(rp = isp->requests; rp; rp = rp->next_request){
- if (freeme != NULL){
- /* frees rp's after the for loop goes on to the next_request */
- free(freeme);
- freeme = NULL;
- }
- if ((timercmp(&rp->expire, &now, <))){
- /* this timer has expired */
- if (rp->retries >= sp->retries){
- if (rp->callback) {
- callback = rp->callback;
- magic = rp->cb_data;
- } else {
- callback = sp->callback;
- magic = sp->callback_magic;
- }
- /* No more chances, delete this entry */
- if (callback)
- callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, magic);
- if (isp->requests == rp){
- isp->requests = rp->next_request;
- if (isp->requestsEnd == rp)
- isp->requestsEnd = NULL;
- } else {
- orp->next_request = rp->next_request;
- if (isp->requestsEnd == rp)
- isp->requestsEnd = orp;
- }
- snmp_free_pdu(rp->pdu); /* FIX rp is already free'd! */
- freeme = rp;
- continue; /* don't update orp below */
- } else {
- if (snmp_resend_request(slp, rp, TRUE)) break;
- }
- }
- orp = rp;
- }
- if (freeme != NULL){
- free(freeme);
- freeme = NULL;
- }
- }
- /* lexicographical compare two object identifiers.
- * Returns -1 if name1 < name2,
- * 0 if name1 = name2,
- * 1 if name1 > name2
- *
- * Caution: this method is called often by
- * command responder applications (ie, agent).
- */
- int
- snmp_oid_compare(const oid *in_name1,
- size_t len1,
- const oid *in_name2,
- size_t len2)
- {
- register int len, res;
- register const oid * name1 = in_name1;
- register const oid * name2 = in_name2;
- /* len = minimum of len1 and len2 */
- if (len1 < len2)
- len = len1;
- else
- len = len2;
- /* find first non-matching OID */
- while(len-- > 0){
- res = *(name1++) - *(name2++);
- if (res < 0)
- return -1;
- if (res > 0)
- return 1;
- }
- /* both OIDs equal up to length of shorter OID */
- if (len1 < len2)
- return -1;
- if (len2 < len1)
- return 1;
- return 0;
- }
- /*
- * Add a variable with the requested name to the end of the list of
- * variables for this pdu.
- */
- struct variable_list *
- snmp_pdu_add_variable(struct snmp_pdu *pdu,
- oid *name,
- size_t name_length,
- u_char type,
- u_char *value,
- size_t len)
- {
- return snmp_varlist_add_variable(&pdu->variables, name, name_length, type,
- value, len);
- }
- /*
- * Add a variable with the requested name to the end of the list of
- * variables for this pdu.
- */
- struct variable_list *
- snmp_varlist_add_variable(struct variable_list **varlist,
- oid *name,
- size_t name_length,
- u_char type,
- u_char *value,
- size_t len)
- {
- struct variable_list *vars, *vtmp;
- int largeval = 1;
- if (varlist == NULL)
- return NULL;
- vars = (struct variable_list *)malloc(sizeof(struct variable_list));
- if (vars == NULL)
- return NULL;
- vars->next_variable = 0; vars->name = 0; vars->val.string = 0;
- /* use built-in storage for smaller values */
- if (len <= sizeof(vars->buf)) {
- vars->val.string = (u_char *)vars->buf;
- largeval = 0;
- }
- vars->type = type;
- vars->val_len = len;
- switch(type){
- case ASN_INTEGER:
- case ASN_UNSIGNED:
- case ASN_TIMETICKS:
- case ASN_IPADDRESS:
- case ASN_COUNTER:
- memmove(vars->val.integer, value, vars->val_len);
- vars->val_len = sizeof(long);
- break;
- case ASN_OBJECT_ID:
- case ASN_PRIV_INCL_RANGE:
- case ASN_PRIV_EXCL_RANGE:
- if (largeval) {
- vars->val.objid = (oid *)malloc(vars->val_len);
- if (vars->val.objid == NULL)
- {
- snmp_free_var (vars);
- return NULL;
- }
- }
- memmove(vars->val.objid, value, vars->val_len);
- break;
- case ASN_OCTET_STR:
- case ASN_OPAQUE:
- case ASN_NSAP:
- if (largeval) {
- vars->val.string = (u_char *)malloc(vars->val_len);
- if (vars->val.string == NULL)
- {
- snmp_free_var(vars);
- return NULL;
- }
- }
- memmove(vars->val.string, value, vars->val_len);
- break;
- case SNMP_NOSUCHOBJECT:
- case SNMP_NOSUCHINSTANCE:
- case SNMP_ENDOFMIBVIEW:
- case ASN_NULL:
- vars->val_len = 0;
- vars->val.string = NULL;
- break;
- #ifdef OPAQUE_SPECIAL_TYPES
- case ASN_OPAQUE_U64:
- case ASN_OPAQUE_I64:
- #endif /* OPAQUE_SPECIAL_TYPES */
- case ASN_COUNTER64:
- vars->val_len = sizeof(struct counter64);
- memmove(vars->val.counter64, value, vars->val_len);
- break;
- #ifdef OPAQUE_SPECIAL_TYPES
- case ASN_OPAQUE_FLOAT:
- vars->val_len = sizeof(float);
- memmove(vars->val.floatVal, value, vars->val_len);
- break;
- case ASN_OPAQUE_DOUBLE:
- vars->val_len = sizeof(double);
- memmove(vars->val.doubleVal, value, vars->val_len);
- #endif /* OPAQUE_SPECIAL_TYPES */
- default:
- snmp_set_detail("Internal error in type switchingn");
- snmp_free_var(vars);
- return (0);
- }
- if (name != NULL && snmp_set_var_objid(vars, name, name_length)) {
- snmp_free_var(vars);
- return (0);
- }
- /* put only qualified variable onto varlist */
- if (*varlist == NULL){
- *varlist = vars;
- } else {
- for(vtmp = *varlist;
- vtmp->next_variable;
- vtmp = vtmp->next_variable)
- ;
- vtmp->next_variable = vars;
- }
- return vars;
- }
- /*
- * Parses dotted notation object identifier
- * into unsigned character array.
- * Returns: SNMPERR_RANGE if any sub-identifier > 255.
- * Returns: SNMPERR_VALUE if input string is not octet string.
- * Returns: non-negative number of sub-identifiers parsed,
- */
- int
- ascii_to_binary(const char *cp,
- u_char *bufp)
- {
- int subidentifier;
- u_char *bp = bufp;
- for(; *cp != ' '; cp++){
- if (isspace(*cp) || *cp == '.')
- continue;
- if (!isdigit(*cp)){
- return SNMPERR_VALUE;
- }
- subidentifier = atoi(cp);
- if (subidentifier > 255){
- return SNMPERR_RANGE;
- }
- *bp++ = (u_char)subidentifier;
- while(isdigit(*cp))
- cp++;
- cp--;
- }
- return bp - bufp;
- }
- int
- hex_to_binary(const char *str,
- u_char *bufp)
- {
- int len, itmp;
- if (!bufp) return -1;
- if (*str && *str == '0' && (*(str+1) == 'x' || *(str+1) == 'X')) str += 2;
- for (len = 0; *str; str++) {
- if (isspace(*str)) continue;
- if (!isxdigit(*str)) return -1;
- len++;
- if (sscanf(str++, "%2x", &itmp) == 0) return -1;
- *bufp++ = (u_char)itmp;
- if (!*str) return -1; /* odd number of chars is an error */
- }
- return len;
- }
- /*
- * Add a variable with the requested name to the end of the list of
- * variables for this pdu.
- * Returns:
- * may set these error types :
- * SNMPERR_RANGE - type, value, or length not found or out of range
- * SNMPERR_VALUE - value is not correct
- * SNMPERR_BAD_NAME - name is not found
- *
- * returns 0 if success, error if failure.
- */
- int
- snmp_add_var(struct snmp_pdu *pdu,
- oid *name,
- size_t name_length,
- char type,
- const char *value)
- {
- int result = 0;
- u_char buf[SPRINT_MAX_LEN];
- size_t tint;
- long ltmp;
- struct tree *tp;
- struct enum_list *ep;
- #ifdef UCD_SNMP
- struct range_list *rp;
- #endif
- #ifdef OPAQUE_SPECIAL_TYPES
- double dtmp;
- float ftmp;
- struct counter64 c64tmp;
- #endif /* OPAQUE_SPECIAL_TYPES */
- switch(type){
- case 'i':
- tp = get_tree(name, name_length, get_tree_head());
- if (sscanf(value, "%ld", <mp) != 1) {
- ep = tp ? tp->enums : NULL;
- while (ep) {
- if (strcmp(value, ep->label) == 0) {
- ltmp = ep->value;
- break;
- }
- ep = ep->next;
- }
- if (!ep) {
- result = SNMPERR_BAD_NAME;
- snmp_set_detail(value);
- break;
- }
- }
- #ifdef UCD_SNMP
- if (tp && tp->ranges && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_CHECK_RANGE)) {
- rp = tp->ranges;
- while (rp) {
- if (rp->low <= ltmp && ltmp <= rp->high) break;
- rp = rp->next;
- }
- if (!rp) {
- result = SNMPERR_RANGE;
- snmp_set_detail("Value");
- break;
- }
- }
- #endif
- snmp_pdu_add_variable(pdu, name, name_length, ASN_INTEGER,
- (u_char *) <mp, sizeof(ltmp));
- break;
- case 'u':
- if (sscanf(value, "%lu", <mp) == 1)
- snmp_pdu_add_variable(pdu, name, name_length, ASN_UNSIGNED,
- (u_char *) <mp, sizeof(ltmp));
- else goto fail;
- break;
- case 'c':
- if (sscanf(value, "%lu", <mp) == 1)
- snmp_pdu_add_variable(pdu, name, name_length, ASN_COUNTER,
- (u_char *) <mp, sizeof(ltmp));
- else goto fail;
- break;
- case 't':
- if (sscanf(value, "%lu", <mp) == 1)
- snmp_pdu_add_variable(pdu, name, name_length, ASN_TIMETICKS,
- (u_char *) <mp, sizeof(long));
- else goto fail;
- break;
- case 'a':
- if ((ltmp = inet_addr(value)) != (long)-1)
- snmp_pdu_add_variable(pdu, name, name_length, ASN_IPADDRESS,
- (u_char *) <mp, sizeof(long));
- else goto fail;
- break;
- case 'o':
- tint = sizeof(buf) / sizeof(oid);
- if (read_objid(value, (oid *)buf, &tint))
- snmp_pdu_add_variable(pdu, name, name_length, ASN_OBJECT_ID, buf,
- sizeof(oid)*tint);
- else result = snmp_errno;
- break;
- case 's':
- case 'x':
- case 'd':
- if (type == 'd'){
- ltmp = ascii_to_binary(value, buf);
- } else if (type == 's'){
- strcpy((char*)buf, value);
- ltmp = strlen((char*)buf);
- } else if (type == 'x'){
- ltmp = hex_to_binary(value, buf);
- }
- if (ltmp < 0) {
- result = SNMPERR_VALUE;
- snmp_set_detail(value);
- break;
- }
- tp = get_tree(name, name_length, get_tree_head());
- #ifdef UCD_SNMP
- if (tp && tp->ranges && !ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DONT_CHECK_RANGE)) {
- rp = tp->ranges;
- while (rp) {
- if (rp->low <= ltmp && ltmp <= rp->high) break;
- rp = rp->next;
- }
- if (!rp) {
- result = SNMPERR_RANGE;
- snmp_set_detail("Length");
- break;
- }
- }
- #endif
- snmp_pdu_add_variable(pdu, name, name_length, ASN_OCTET_STR, buf, ltmp);
- break;
- case 'n':
- snmp_pdu_add_variable(pdu, name, name_length, ASN_NULL, 0, 0);
- break;
- #ifdef OPAQUE_SPECIAL_TYPES
- case 'U':
- if (read64(&c64tmp, value))
- snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_U64,
- (u_char *) &c64tmp, sizeof(c64tmp));
- else goto fail;
- break;
- case 'I':
- if (read64(&c64tmp, value))
- snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_I64,
- (u_char *) &c64tmp, sizeof(c64tmp));
- else goto fail;
- break;
- case 'F':
- if (sscanf(value, "%f", &ftmp) == 1)
- snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_FLOAT,
- (u_char *) &ftmp, sizeof(ftmp));
- else goto fail;
- break;
- case 'D':
- if (sscanf(value, "%lf", &dtmp) == 1)
- snmp_pdu_add_variable(pdu, name, name_length, ASN_OPAQUE_DOUBLE,
- (u_char *) &dtmp, sizeof(dtmp));
- else goto fail;
- break;
- #endif /* OPAQUE_SPECIAL_TYPES */
- default:
- result = SNMPERR_VAR_TYPE;
- sprintf((char *)buf, "%c", type);
- snmp_set_detail((const char *)buf);
- break;
- }
- SET_SNMP_ERROR(result);
- return result;
- fail:
- result = SNMPERR_VALUE;
- snmp_set_detail(value);
- SET_SNMP_ERROR(result);
- return result;
- }
- /*
- * returns NULL or internal pointer to session
- * use this pointer for the other snmp_sess* routines,
- * which guarantee action will occur ONLY for this given session.
- */
- void *
- snmp_sess_pointer(struct snmp_session *session)
- {
- struct session_list *slp;
- snmp_res_lock(MT_LIBRARY_ID, MT_LIB_SESSION);
- for(slp = Sessions; slp; slp = slp->next){
- if (slp->session == session){
- break;
- }
- }
- snmp_res_unlock(MT_LIBRARY_ID, MT_LIB_SESSION);
- if (slp == NULL){
- snmp_errno = SNMPERR_BAD_SESSION; /*MTCRITICAL_RESOURCE*/
- return(NULL);
- }
- return((void *)slp);
- }
- /*
- * Input : an opaque pointer, returned by snmp_sess_open.
- * returns NULL or pointer to session.
- */
- struct snmp_session *
- snmp_sess_session(void *sessp)
- {
- struct session_list *slp = (struct session_list *)sessp;
- if (slp == NULL) return(NULL);
- return (slp->session);
- }
- #ifdef CMU_COMPATIBLE
- char *
- snmp_pdu_type(struct snmp_pdu *PDU)
- {
- switch(PDU->command) {
- case SNMP_MSG_GET:
- return("GET");
- break;
- case SNMP_MSG_GETNEXT:
- return("GETNEXT");
- break;
- case SNMP_MSG_RESPONSE:
- return("RESPONSE");
- break;
- case SNMP_MSG_SET:
- return("SET");
- break;
- case SNMP_MSG_GETBULK:
- return("GETBULK");
- break;
- case SNMP_MSG_INFORM:
- return("INFORM");
- break;
- case SNMP_MSG_TRAP2:
- return("V2TRAP");
- break;
- case SNMP_MSG_REPORT:
- return("REPORT");
- break;
- case SNMP_MSG_TRAP:
- return("V1TRAP");
- break;
- default:
- return("Unknown");
- break;
- }
- }
- /*
- * cmu_snmp_parse - emulate CMU library's snmp_parse.
- *
- * Parse packet, storing results into PDU.
- * Returns community string if success, NULL if fail.
- * WARNING: may return a zero length community string.
- *
- * Note:
- * Some CMU-aware apps call init_mib(), but do not
- * initialize a session.
- * Check Reqid to make sure that this module is initialized.
- */
- u_char *
- cmu_snmp_parse (struct snmp_session *session,
- struct snmp_pdu *pdu,
- u_char *data,
- size_t length)
- {
- u_char *bufp = NULL;
- if (Reqid == 0) {
- snmp_sess_init(session); /* gimme a break! */
- }
- switch(pdu->version) {
- case SNMP_VERSION_1:
- case SNMP_VERSION_2c:
- case SNMP_DEFAULT_VERSION:
- break;
- default:
- return NULL;
- }
- #ifndef NO_INTERNAL_VARLIST
- if (snmp_parse( 0, session, pdu, data, length) != SNMP_ERR_NOERROR){
- return NULL;
- }
- #else
- /*
- * while there are two versions of variable_list:
- * use an internal variable list for snmp_parse;
- * clone the result.
- */
- if (1) {
- struct snmp_pdu *snmp_clone_pdu (struct snmp_pdu *);
- struct snmp_pdu *snmp_2clone_pdu(struct snmp_pdu *from_pdu, struct snmp_pdu *to_pdu);
- struct snmp_pdu *ipdu;
- ipdu = snmp_clone_pdu(pdu);
- if (snmp_parse( 0, session, ipdu, data, length) != SNMP_ERR_NOERROR){
- snmp_free_internal_pdu(ipdu);
- return NULL;
- }
- pdu = snmp_2clone_pdu(ipdu, pdu);
- snmp_free_internal_pdu(ipdu);
- }
- #endif /* NO_INTERNAL_VAR_LIST */
- /* Add a null to meet the caller's expectations. */
- bufp = (u_char *)malloc(1+pdu->community_len);
- if (bufp && pdu->community_len) {
- memcpy(bufp, pdu->community, pdu->community_len);
- bufp[pdu->community_len] = ' ';
- }
- return(bufp);
- }
- #endif /* CMU_COMPATIBLE */
- /* snmp_duplicate_objid: duplicates (mallocs) an objid based on the
- input objid */
- oid *
- snmp_duplicate_objid(oid *objToCopy, size_t objToCopyLen)
- {
- oid *returnOid;
- returnOid = (oid *) malloc(objToCopyLen*sizeof(oid));
- if (returnOid) {
- memmove(returnOid, objToCopy, objToCopyLen*sizeof(oid));
- }
- return returnOid;
- }
- /* generic statistics counter functions */
- static u_int statistics[MAX_STATS];
- u_int
- snmp_increment_statistic(int which)
- {
- if (which >= 0 && which < MAX_STATS) {
- statistics[which]++;
- return statistics[which];
- }
- return 0;
- }
- u_int
- snmp_increment_statistic_by(int which, int count)
- {
- if (which >= 0 && which < MAX_STATS) {
- statistics[which] += count;
- return statistics[which];
- }
- return 0;
- }
- u_int
- snmp_get_statistic(int which)
- {
- if (which >= 0 && which < MAX_STATS)
- {
- if (which == STAT_SNMPINTOTALREQVARS)
- return (statistics[STAT_SNMPINGETREQUESTS] + statistics[STAT_SNMPINGETNEXTS]);
- if (which == STAT_SNMPINTOTALSETVARS)
- return statistics[STAT_SNMPINSETREQUESTS];
- return statistics[which];
- }
- return 0;
- }
- void
- snmp_init_statistics(void)
- {
- memset(statistics, 0, sizeof(statistics));
- }
- /* returns the length of a socket structure */
- size_t snmp_socket_length( int family)
- {
- size_t length;
- switch (family)
- {
- #ifdef UCD_SNMP
- #ifndef cygwin
- #ifndef WIN32
- #ifdef AF_UNIX
- case AF_UNIX:
- length = sizeof (struct sockaddr_un);
- break;
- #endif /* AF_UNIX */
- #endif
- #endif
- #ifndef aix3
- #ifdef AF_LINK
- case AF_LINK:
- #ifdef _MAX_SA_LEN
- length = _MAX_SA_LEN;
- #elif SOCK_MAXADDRLEN
- length = SOCK_MAXADDRLEN;
- #else
- length = sizeof (struct sockaddr_dl);
- #endif
- break;
- #endif /* AF_LINK */
- #endif
- #endif
- case AF_INET:
- length = sizeof (struct soaddr_in);
- break;
- default:
- length = sizeof (struct soaddr);
- break;
- }
- return length;
- }
- /*
- * For compatibility with applications built using
- * previous versions only.
- */
- /* use <struct snmp_session *)->s_snmp_errno instead */
- int snmp_get_errno (void) { return SNMPERR_SUCCESS; }
- /* synch_reset and synch_setup are no longer used. */
- void snmp_synch_reset (struct snmp_session * notused) {}
- void snmp_synch_setup (struct snmp_session * notused) {}
- /* provide for backwards compatibility */
- void
- snmp_set_dump_packet(int x) {
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET, x);
- }
- int
- snmp_get_dump_packet(void) {
- return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_DUMP_PACKET);
- }
- void
- snmp_set_quick_print(int x) {
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT, x);
- }
- int
- snmp_get_quick_print(void) {
- return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_QUICK_PRINT);
- }
- void
- snmp_set_suffix_only(int x) {
- ds_set_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY, x);
- }
- int
- snmp_get_suffix_only(void) {
- return ds_get_int(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY);
- }
- void
- snmp_set_full_objid(int x) {
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_FULL_OID, x);
- }
- int
- snmp_get_full_objid(void) {
- return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_PRINT_SUFFIX_ONLY);
- }
- void
- snmp_set_random_access(int x) {
- ds_set_boolean(DS_LIBRARY_ID, DS_LIB_RANDOM_ACCESS, x);
- }
- int
- snmp_get_random_access(void) {
- return ds_get_boolean(DS_LIBRARY_ID, DS_LIB_RANDOM_ACCESS);
- }
- int change_session_localaddr(struct snmp_session *session,DEVICE_ETERNAL_ID ID)
- {
- struct session_list *slp;
- struct snmp_internal_session *isp = NULL;
- struct soaddr_in locname;
- int namelen=sizeof(struct soaddr_in);
- /*** sun define 2000.03.21 ***/
- /* struct soaddr_intf sin; */
- int ret;
- /*** sun define end ***/
- for(slp = Sessions; slp; slp = slp->next){
- if (slp->session == session){
- isp = slp->internal;
- break;
- }
- }
- if (isp == NULL){
- snmp_errno = SNMPERR_BAD_SESSION;
- snmp_trace("isp==nulln");
- return snmp_errno;
- }
- if(so_getsockname(isp->sd,(struct soaddr*)&locname,&namelen)){
- snmp_errno = SNMPERR_BAD_SESSION;
- snmp_trace("so_getsockname failn");
- return snmp_errno;
- }
- if(namelen==0){/*not bind*/
- snmp_trace("namelen==0n");
- return -1;
- }
- if((ret =bind_intf(isp->sd, ID))!=0)
- {
- snmp_trace("bind_intf error %dn",ret);
- return -1;
- }
- return 0;
- }
- int change_session_sourceaddr(uint32 source_ip_addr)
- {
- struct session_list *slp;
- struct snmp_internal_session *isp = NULL;
- struct snmp_session *session;
- int len;
- int rc;
- int sd;
- fd_set fdset;
- struct soaddr_in snmp_sour_addr;
- for(slp = Sessions; slp; slp = slp->next){
- if (slp==NULL) break;
- isp = slp->internal;
- session = slp->session;
- if (so_getsockname(isp->sd, (struct soaddr *) &snmp_sour_addr, &len) < 0) {
- vty_output("Can not get source addrn");
- return -1;
- }
- if (isp->sd >=0 )
- {
- int numfds;
- struct timeval timeout, *tvp;
- int block;
- tvp = &timeout;
- tvp->tv_sec = 0;
- tvp->tv_usec = 0;
- numfds = 0;
- FD_ZERO(&fdset);
- block = 0;
- sd = so_socket(AF_INET, SOCK_DGRAM, 0);
- if (sd < 0){
- session->s_snmp_errno = SNMPERR_NO_SOCKET;
- session->s_errno = errno;
- snmp_set_detail(strerror(errno));
- return -1;
- }
- snmp_sess_select_info(NULL, &numfds, &fdset, tvp, &block);
- if (FD_ISSET(isp->sd, &fdset))
- {
- FD_CLR(isp->sd, &fdset);
- so_close(isp->sd);
- isp->sd =-1;
- }
- isp->sd = sd;
- FD_SET(isp->sd, &fdset);
- snmp_sour_addr.sin_addr.s_addr= htonl(source_ip_addr);
- rc= so_bind(isp->sd, (struct soaddr *)&snmp_sour_addr, sizeof(struct soaddr_in));
- if (rc!= 0)
- {
- vty_output("bind source ip fail!n");
- session->s_snmp_errno = SNMPERR_BAD_LOCPORT;
- session->s_errno = errno;
- snmp_set_detail(strerror(errno));
- return -1;
- }
- }
- }
- return 0;
- }
- /*
- * get the current communitiy, used only in SNMP task
- */
- const char * snmp_get_current_community()
- {
- return snmp_current_community;
- }
- void SNMP_ENTERPRISE_MODIFY(oid * oid_array, size_t arr_len)
- {
- assert(NULL != oid_array);
- if ((arr_len >= 6) && (oid_array[0] == 1) && (oid_array[1] == 3) && (oid_array[2] == 6) && (oid_array[3] == 1)
- && (oid_array[4] == 4) && (oid_array[5] == 1) )
- {
- if (eprom_extend() && eprom_oem())
- {
- if (ENTERPRISE_NUMBER == default_enterprise[6])
- oid_array[6] = eprom_vendor_id();
- else
- oid_array[6] = default_enterprise[6];
- #if 0
- Print("SNMP REGISTER OID = %d.%d.%d.%d.%d.%d.%d.%dn",oid_array[0],oid_array[1]
- ,oid_array[2],oid_array[3],oid_array[4],oid_array[5],oid_array[6],oid_array[7]);
- #endif
- }
- }
- }