📄 smux.c
字号:
smux_list_detach(&ActiveRegs, &rptr); free(rptr); } smux_send_rrsp(sd, rpriority); return ptr; } /* * search the passive list for this registration */ rptr = smux_find_match(PassiveRegs, sd, oid_name, oid_name_len, priority); if (rptr) { rpriority = rptr->sr_priority; smux_list_detach(&PassiveRegs, &rptr); free(rptr); smux_send_rrsp(sd, rpriority); return ptr; } /* * This peer cannot unregister the tree, it does not * * belong to him. Send him an error. */ smux_send_rrsp(sd, -1); return ptr; } else if ((operation == SMUX_REGOP_REGISTER_RO) || (operation == SMUX_REGOP_REGISTER_RW)) { if (priority < -1) { DEBUGMSGTL(("smux", "[smux_rreq_process] peer fd %d invalid priority", sd, priority)); smux_send_rrsp(sd, -1); return NULL; } if ((nrptr = malloc(sizeof(smux_reg))) == NULL) { snmp_log_perror("[smux_rreq_process] malloc"); smux_send_rrsp(sd, -1); return NULL; } nrptr->sr_priority = priority; nrptr->sr_name_len = oid_name_len; nrptr->sr_fd = sd; for (i = 0; i < (int) oid_name_len; i++) nrptr->sr_name[i] = oid_name[i]; /* * See if this tree matches or scopes any of the * * active trees. */ for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) { result = snmp_oid_compare(oid_name, oid_name_len, rptr->sr_name, rptr->sr_name_len); if (result == 0) { if ((oid_name_len == rptr->sr_name_len)) { if ((nrptr->sr_priority == -1)) { nrptr->sr_priority = rptr->sr_priority; do { nrptr->sr_priority++; } while (smux_list_add(&PassiveRegs, nrptr)); goto done; } else if (nrptr->sr_priority < rptr->sr_priority) { /* * Better priority. There are no better * * priorities for this tree in the passive list, * * so replace the current active tree. */ smux_replace_active(rptr, nrptr); goto done; } else { /* * Equal or worse priority */ do { nrptr->sr_priority++; } while (smux_list_add(&PassiveRegs, nrptr) == -1); goto done; } } else if (oid_name_len < rptr->sr_name_len) { /* * This tree scopes a current active * * tree. Replace the current active tree. */ smux_replace_active(rptr, nrptr); goto done; } else { /* oid_name_len > rptr->sr_name_len */ /* * This tree is scoped by a current * * active tree. */ do { nrptr->sr_priority++; } while (smux_list_add(&PassiveRegs, nrptr) == -1); goto done; } } } /* * We didn't find it in the active list. Add it at * * the requested priority. */ if (nrptr->sr_priority == -1) nrptr->sr_priority = 0; smux_list_add(&ActiveRegs, nrptr); register_mib("smux", (struct variable *) smux_variables, sizeof(struct variable2), 1, nrptr->sr_name, nrptr->sr_name_len); done: smux_send_rrsp(sd, nrptr->sr_priority); return ptr; } else { DEBUGMSGTL(("smux", "[smux_rreq_process] unknown operation\n")); smux_send_rrsp(sd, -1); return NULL; }}/* * Find the registration with a matching descriptor, OID and priority. If * the priority is -1 then find a registration with a matching descriptor, * a matching OID, and the highest priority. */static smux_reg *smux_find_match(smux_reg * regs, int sd, oid * oid_name, size_t oid_name_len, long priority){ smux_reg *rptr, *bestrptr; bestrptr = NULL; for (rptr = regs; rptr; rptr = rptr->sr_next) { if (rptr->sr_fd != sd) continue; if (snmp_oid_compare (rptr->sr_name, rptr->sr_name_len, oid_name, oid_name_len)) continue; if (rptr->sr_priority == priority) return rptr; if (priority != -1) continue; if (bestrptr) { if (bestrptr->sr_priority > rptr->sr_priority) bestrptr = rptr; } else { bestrptr = rptr; } } return bestrptr;}static voidsmux_replace_active(smux_reg * actptr, smux_reg * pasptr){ smux_list_detach(&ActiveRegs, &actptr); unregister_mib(actptr->sr_name, actptr->sr_name_len); smux_list_detach(&PassiveRegs, &pasptr); (void) smux_list_add(&ActiveRegs, pasptr); register_mib("smux", (struct variable *) smux_variables, sizeof(struct variable2), 1, pasptr->sr_name, pasptr->sr_name_len); free(actptr);}static voidsmux_list_detach(smux_reg ** head, smux_reg ** m_remove){ smux_reg *rptr, *rptr2; if (*head == NULL) { DEBUGMSGTL(("smux", "[smux_list_detach] Ouch!")); return; } if (*head == *m_remove) { *m_remove = *head; *head = (*head)->sr_next; return; } for (rptr = *head, rptr2 = rptr->sr_next; rptr2; rptr2 = rptr2->sr_next, rptr = rptr->sr_next) { if (rptr2 == *m_remove) { *m_remove = rptr2; rptr->sr_next = rptr2->sr_next; return; } }}/* * Attempt to add a registration (in order) to a list. If the * add fails (because of an existing registration with equal * priority) return -1. */static intsmux_list_add(smux_reg ** head, smux_reg * add){ smux_reg *rptr; int result; if (*head == NULL) { *head = add; (*head)->sr_next = NULL; return 0; } for (rptr = *head; rptr->sr_next; rptr = rptr->sr_next) { 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)) { /* * same tree, same pri, nope */ return -1; } 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; } } /* * compare the last one */ if ((snmp_oid_compare(add->sr_name, add->sr_name_len, rptr->sr_name, rptr->sr_name_len) == 0) && add->sr_priority == rptr->sr_priority) return -1; 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]; size_t length = SMUXMAXPKTSIZE; 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) { snmp_log_perror("[smux_snmp_process] peek failed"); smux_peer_cleanup(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 */ length = recv(sd, (char *) result, length, 0); if (length < 0) { snmp_log_perror("[smux_snmp_process] recv failed"); smux_peer_cleanup(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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -