📄 smux.c
字号:
} else if (result < 0) { /* * this can only happen if we go before the head */ add->sr_next = *head; *head = add; return 0; } else if ((snmp_oid_compare(add->sr_name, add->sr_name_len, rptr->sr_next->sr_name, rptr->sr_next->sr_name_len)) < 0) { /* * insert here */ add->sr_next = rptr->sr_next; rptr->sr_next = add; return 0; } prev = rptr; } /* * compare the last one */ result = snmp_oid_compare(add->sr_name, add->sr_name_len, rptr->sr_name, rptr->sr_name_len); if ((result == 0) && add->sr_priority == rptr->sr_priority) return -1; else if (result < 0 ) { add->sr_next = rptr; if ( prev ) { prev->sr_next = add; } else { *head = add; } } else { rptr->sr_next = add; add->sr_next = NULL; } return 0;}/* * Find a replacement for this registration. In order * of preference: * * - Least difference in subtree length * - Best (lowest) priority * * For example, if we need to replace .1.3.6.1.69, * we would pick .1.3.6.1.69.1 instead of .1.3.6.69.1.1 * */static smux_reg *smux_find_replacement(oid * name, size_t name_len){ smux_reg *rptr, *bestptr; int bestlen, difflen; bestlen = SMUX_MAX_PRIORITY; bestptr = NULL; for (rptr = PassiveRegs; rptr; rptr = rptr->sr_next) { if (!snmp_oidtree_compare(rptr->sr_name, rptr->sr_name_len, name, name_len)) { if ((difflen = rptr->sr_name_len - name_len) < bestlen) { bestlen = difflen; bestptr = rptr; } else if ((difflen == bestlen) && (rptr->sr_priority < bestptr->sr_priority)) bestptr = rptr; } } return bestptr;}u_char *smux_snmp_process(int exact, oid * objid, size_t * len, size_t * return_len, u_char * return_type, int sd){ u_char packet[SMUXMAXPKTSIZE], *ptr, result[SMUXMAXPKTSIZE]; int length = SMUXMAXPKTSIZE; int tmp_length; u_char type; size_t packet_len; /* * Send the query to the peer */ smux_reqid++; if (exact) type = SMUX_GET; else type = SMUX_GETNEXT; if (smux_build(type, smux_reqid, objid, len, 0, NULL, *len, packet, &length) < 0) { snmp_log(LOG_ERR, "[smux_snmp_process]: smux_build failed\n"); return NULL; } DEBUGMSGTL(("smux", "[smux_snmp_process] oid from build: ")); DEBUGMSGOID(("smux", objid, *len)); DEBUGMSG(("smux", "\n")); if (send(sd, (char *) packet, length, 0) < 0) { snmp_log_perror("[smux_snmp_process] send failed"); } DEBUGMSGTL(("smux", "[smux_snmp_process] Sent %d request to peer; %d bytes\n", (int) type, length)); while (1) { /* * peek at what's received */ length = recv(sd, (char *) result, SMUXMAXPKTSIZE, MSG_PEEK); if (length <= 0) { if ((length == -1) && ((errno == EINTR) || (errno == EAGAIN))) { continue; } else { snmp_log_perror("[smux_snmp_process] peek failed"); smux_peer_cleanup(sd); smux_snmp_select_list_del(sd); return NULL; } } DEBUGMSGTL(("smux", "[smux_snmp_process] Peeked at %d bytes\n", length)); DEBUGDUMPSETUP("smux_snmp_process", result, length); /* * determine if we received more than one packet */ packet_len = length; ptr = asn_parse_header(result, &packet_len, &type); packet_len += (ptr - result); if (length > packet_len) { /* * set length to receive only the first packet */ length = packet_len; } /* * receive the first packet */ tmp_length = length; do { length = tmp_length; length = recv(sd, (char *) result, length, 0); } while((length == -1) && ((errno == EINTR) || (errno == EAGAIN))); if (length <= 0) { snmp_log_perror("[smux_snmp_process] recv failed"); smux_peer_cleanup(sd); smux_snmp_select_list_del(sd); return NULL; } DEBUGMSGTL(("smux", "[smux_snmp_process] Received %d bytes\n", length)); if (result[0] == SMUX_TRAP) { DEBUGMSGTL(("smux", "[smux_snmp_process] Received trap\n")); snmp_log(LOG_INFO, "Got trap from peer on fd %d\n", sd); ptr = asn_parse_header(result, &length, &type); smux_trap_process(ptr, &length); /* * go and peek at received data again */ /* * we could receive the reply or another trap */ } else { /* * Interpret reply */ ptr = smux_parse(result, objid, len, return_len, return_type); /* * ptr will point to query result or NULL if error */ break; } } /* while (1) */ return ptr;}static u_char *smux_parse(u_char * rsp, oid * objid, size_t * oidlen, size_t * return_len, u_char * return_type){ size_t length = SMUXMAXPKTSIZE; u_char *ptr, type; long reqid, errstat, errindex; ptr = rsp; /* * Return pointer to the snmp/smux return value. * return_len should contain the number of bytes in the value * returned above. * objid is the next object, with len for GETNEXT. * objid and len are not changed for GET */ ptr = asn_parse_header(ptr, &length, &type); if (ptr == NULL || type != SNMP_MSG_RESPONSE) return NULL; if ((ptr = asn_parse_int(ptr, &length, &type, &reqid, sizeof(reqid))) == NULL) { DEBUGMSGTL(("smux", "[smux_parse] parse of reqid failed\n")); return NULL; } if ((ptr = asn_parse_int(ptr, &length, &type, &errstat, sizeof(errstat))) == NULL) { DEBUGMSGTL(("smux", "[smux_parse] parse of error status failed\n")); return NULL; } if ((ptr = asn_parse_int(ptr, &length, &type, &errindex, sizeof(errindex))) == NULL) { DEBUGMSGTL(("smux", "[smux_parse] parse of error index failed\n")); return NULL; } /* * XXX How to send something intelligent back in case of an error */ DEBUGMSGTL(("smux", "[smux_parse] Message type %d, reqid %d, errstat %d, \n\terrindex %d\n", (int) type, reqid, errstat, errindex)); if (ptr == NULL || errstat != SNMP_ERR_NOERROR) return NULL; /* * stuff to return */ return (smux_parse_var (ptr, &length, objid, oidlen, return_len, return_type));}static u_char *smux_parse_var(u_char * varbind, size_t * varbindlength, oid * objid, size_t * oidlen, size_t * varlength, u_char * vartype){ oid var_name[MAX_OID_LEN]; size_t var_name_len; size_t var_val_len; u_char *var_val; size_t str_len, objid_len; size_t len; u_char *ptr; u_char type; ptr = varbind; len = *varbindlength; DEBUGMSGTL(("smux", "[smux_parse_var] before any processing: ")); DEBUGMSGOID(("smux", objid, *oidlen)); DEBUGMSG(("smux", "\n")); ptr = asn_parse_header(ptr, &len, &type); if (ptr == NULL || type != (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { snmp_log(LOG_NOTICE, "[smux_parse_var] Panic: type %d\n", (int) type); return NULL; } /* * get hold of the objid and the asn1 coded value */ var_name_len = MAX_OID_LEN; ptr = snmp_parse_var_op(ptr, var_name, &var_name_len, vartype, &var_val_len, &var_val, &len); *oidlen = var_name_len; memcpy(objid, var_name, var_name_len * sizeof(oid)); DEBUGMSGTL(("smux", "[smux_parse_var] returning oid : ")); DEBUGMSGOID(("smux", objid, *oidlen)); DEBUGMSG(("smux", "\n")); /* * XXX */ len = SMUXMAXPKTSIZE; DEBUGMSGTL(("smux", "[smux_parse_var] Asn coded len of var %d, type %d\n", var_val_len, (int) *vartype)); switch ((short) *vartype) { case ASN_INTEGER: *varlength = sizeof(long); asn_parse_int(var_val, &len, vartype, (long *) &smux_long, *varlength); return (u_char *) & smux_long; break; case ASN_COUNTER: case ASN_GAUGE: case ASN_TIMETICKS: case ASN_UINTEGER: *varlength = sizeof(u_long); asn_parse_unsigned_int(var_val, &len, vartype, (u_long *) & smux_ulong, *varlength); return (u_char *) & smux_ulong; break; case ASN_COUNTER64: *varlength = sizeof(smux_counter64); asn_parse_unsigned_int64(var_val, &len, vartype, (struct counter64 *) &smux_counter64, *varlength); return (u_char *) & smux_counter64; break; case ASN_IPADDRESS: *varlength = 4; /* * consume the tag and length, but just copy here * because we know it is an ip address */ if ((var_val = asn_parse_header(var_val, &len, &type)) == NULL) return NULL; memcpy((u_char *) & (smux_sa.sin_addr.s_addr), var_val, *varlength); return (u_char *) & (smux_sa.sin_addr.s_addr); break; case ASN_OCTET_STR: /* * XXX */ if (len == 0) return NULL; str_len = SMUXMAXSTRLEN; asn_parse_string(var_val, &len, vartype, smux_str, &str_len); *varlength = str_len; return smux_str; break; case ASN_OPAQUE: case ASN_NSAP: case ASN_OBJECT_ID: objid_len = MAX_OID_LEN; asn_parse_objid(var_val, &len, vartype, smux_objid, &objid_len); *varlength = objid_len * sizeof(oid); return (u_char *) smux_objid; break; case SNMP_NOSUCHOBJECT: case SNMP_NOSUCHINSTANCE: case SNMP_ENDOFMIBVIEW: case ASN_NULL: return NULL; break; case ASN_BIT_STR: /* * XXX */ if (len == 0) return NULL; str_len = SMUXMAXSTRLEN; asn_parse_bitstring(var_val, &len, vartype, smux_str, &str_len); *varlength = str_len; return (u_char *) smux_str; break; default: snmp_log(LOG_ERR, "bad type returned (%x)\n", *vartype); return NULL; break; }}/* * XXX This is a bad hack - do not want to muck with ucd code */static intsmux_build(u_char type, long reqid, oid * objid, size_t * oidlen, u_char val_type, u_char * val, size_t val_len, u_char * packet, size_t * length){ u_char *ptr, *save1, *save2; size_t len; long errstat = 0; long errindex = 0; /* * leave space for Seq and length */ save1 = packet; ptr = packet + 4; len = *length - 4; /* * build reqid */ ptr = asn_build_int(ptr, &len, (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), &reqid, sizeof(reqid)); if (ptr == NULL) { return -1; } /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -