708370 - net-snmp increments request-id when generating multiple SMUX-PDUs for a SMUX peer Source: upstream, copied from master after commit 3fa0088c63fe0dd73417af94d888333192194093 (too many individial commits to list) diff -up net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.c.rhel net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.c --- net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.c.rhel 2012-07-31 14:13:18.069018537 +0200 +++ net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.c 2012-07-31 13:49:55.000000000 +0200 @@ -66,7 +66,6 @@ #include #include "smux.h" -#include "mibdefs.h" #include "snmpd.h" netsnmp_feature_require(snprint_objid) @@ -103,10 +102,9 @@ static int smux_pdu_process(int, u_ static int smux_send_rrsp(int, int); static smux_reg *smux_find_match(smux_reg *, int, oid *, size_t, long); static smux_reg *smux_find_replacement(oid *, size_t); -u_char *var_smux(struct variable *, oid *, size_t *, int, size_t *, - WriteMethod ** write_method); -int var_smux_write(int, u_char *, u_char, size_t, u_char *, - oid *, size_t); +u_char *var_smux_get(oid *, size_t, oid *, size_t *, int, size_t *, + u_char *); +int var_smux_write(int, u_char *, u_char, size_t, oid *, size_t); static smux_reg *ActiveRegs; /* Active registrations */ static smux_reg *PassiveRegs; /* Currently unused registrations */ @@ -114,14 +112,6 @@ static smux_reg *PassiveRegs; /* Curre static smux_peer_auth *Auths[SMUX_MAX_PEERS]; /* Configured peers */ static int nauths, npeers = 0; -struct variable2 smux_variables[] = { - /* - * bogus entry, as in pass.c - */ - {MIBINDEX, ASN_INTEGER, NETSNMP_OLDAPI_RWRITE, - var_smux, 0, {MIBINDEX}}, -}; - void @@ -244,7 +234,7 @@ real_init_smux(void) #endif netsnmp_sockaddr_in( &lo_socket, smux_socket, SMUXPORT ); - if ((smux_listen_sd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + if ((smux_listen_sd = (int) socket(AF_INET, SOCK_STREAM, 0)) < 0) { snmp_log_perror("[init_smux] socket failed"); return; } @@ -291,21 +281,88 @@ real_init_smux(void) smux_listen_sd, ntohs(lo_socket.sin_port))); } +static int +smux_handler(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + u_char *access = NULL; + size_t var_len; + int exact = 1; + int status = 0; + u_char var_type; + static long old_reqid = -1; + static long old_sessid = -1; + long new_reqid, new_sessid; + + /* Increment the reqid of outgoing SMUX messages only when processing + * new incoming SNMP message, i.e. when reqid or session id chamges */ + new_reqid = reqinfo->asp->pdu->reqid; + new_sessid = reqinfo->asp->session->sessid; + DEBUGMSGTL(("smux", "smux_handler: incoming reqid=%ld, sessid=%ld\n", + new_reqid, new_sessid)); + if (old_reqid != new_reqid || old_sessid != new_sessid) { + smux_reqid++; + old_reqid = new_reqid; + old_sessid = new_sessid; + } + + switch (reqinfo->mode) { + case MODE_GETNEXT: + case MODE_GETBULK: + exact = 0; + } + + for (; requests; requests = requests->next) { + switch(reqinfo->mode) { + case MODE_GET: + case MODE_GETNEXT: + case MODE_SET_RESERVE1: + access = var_smux_get(reginfo->rootoid, + reginfo->rootoid_len, + requests->requestvb->name, + &requests->requestvb->name_length, + exact, + &var_len, + &var_type); + if (access) + if (reqinfo->mode != MODE_SET_RESERVE1) + snmp_set_var_typed_value(requests->requestvb, + var_type, access, var_len); + if (reqinfo->mode != MODE_SET_RESERVE1) + break; + /* fall through if MODE_SET_RESERVE1 */ + + default: + /* SET processing */ + status = var_smux_write(reqinfo->mode, + requests->requestvb->val.string, + requests->requestvb->type, + requests->requestvb->val_len, + requests->requestvb->name, + requests->requestvb->name_length); + if (status != SNMP_ERR_NOERROR) { + netsnmp_set_request_error(reqinfo, requests, status); + } + } + } + return SNMP_ERR_NOERROR; +} + u_char * -var_smux(struct variable * vp, - oid * name, - size_t * length, - int exact, size_t * var_len, WriteMethod ** write_method) +var_smux_get(oid *root, size_t root_len, + oid * name, size_t * length, + int exact, size_t * var_len, u_char *var_type) { - u_char *valptr, val_type; + u_char *valptr; smux_reg *rptr; - *write_method = var_smux_write; /* * search the active registration list */ for (rptr = ActiveRegs; rptr; rptr = rptr->sr_next) { - if (0 >= snmp_oidtree_compare(vp->name, vp->namelen, rptr->sr_name, + if (0 >= snmp_oidtree_compare(root, root_len, rptr->sr_name, rptr->sr_name_len)) break; } @@ -315,7 +372,7 @@ var_smux(struct variable * vp, return NULL; valptr = smux_snmp_process(exact, name, length, - var_len, &val_type, rptr->sr_fd); + var_len, var_type, rptr->sr_fd); if (valptr == NULL) return NULL; @@ -328,10 +385,6 @@ var_smux(struct variable * vp, */ return NULL; } else { - /* - * set the type and return the value - */ - vp->type = val_type; return valptr; } } @@ -341,7 +394,7 @@ var_smux_write(int action, u_char * var_val, u_char var_val_type, size_t var_val_len, - u_char * statP, oid * name, size_t name_len) + oid * name, size_t name_len) { smux_reg *rptr; u_char buf[SMUXMAXPKTSIZE], *ptr, sout[3], type; @@ -589,7 +642,7 @@ smux_accept(int sd) */ DEBUGMSGTL(("smux", "[smux_accept] Calling accept()\n")); errno = 0; - if ((fd = accept(sd, (struct sockaddr *) &in_socket, &alen)) < 0) { + if ((fd = (int) accept(sd, (struct sockaddr *) &in_socket, &alen)) < 0) { snmp_log_perror("[smux_accept] accept failed"); return -1; } else { @@ -1000,6 +1053,7 @@ smux_rreq_process(int sd, u_char * ptr, int i, result; u_char type; smux_reg *rptr, *nrptr; + netsnmp_handler_registration *reg; oid_name_len = MAX_OID_LEN; ptr = asn_parse_objid(ptr, len, &type, oid_name, &oid_name_len); @@ -1157,17 +1211,27 @@ smux_rreq_process(int sd, u_char * ptr, */ if (nrptr->sr_priority == -1) nrptr->sr_priority = 0; + + reg = netsnmp_create_handler_registration("smux", + smux_handler, + nrptr->sr_name, + nrptr->sr_name_len, + HANDLER_CAN_RWRITE); + if (reg == NULL) { + snmp_log(LOG_ERR, "SMUX: cannot create new smux peer " + "registration\n"); + smux_send_rrsp(sd, -1); + free(nrptr); + return NULL; + } + if (netsnmp_register_handler(reg) != MIB_REGISTERED_OK) { + snmp_log(LOG_ERR, "SMUX: cannot register new smux peer\n"); + smux_send_rrsp(sd, -1); + free(nrptr); + return NULL; + } + nrptr->reginfo = reg; smux_list_add(&ActiveRegs, nrptr); - if (register_mib("smux", (struct variable *) - smux_variables, sizeof(struct variable2), - 1, nrptr->sr_name, nrptr->sr_name_len) - != SNMPERR_SUCCESS) { - DEBUGMSGTL(("smux", "[smux_rreq_process] Failed to register subtree\n")); - smux_list_detach(&ActiveRegs, nrptr); - free(nrptr); - smux_send_rrsp(sd, -1); - return NULL; - } done: smux_send_rrsp(sd, nrptr->sr_priority); @@ -1214,16 +1278,35 @@ smux_find_match(smux_reg * regs, int sd, static void smux_replace_active(smux_reg * actptr, smux_reg * pasptr) { + netsnmp_handler_registration *reg; + smux_list_detach(&ActiveRegs, actptr); - unregister_mib(actptr->sr_name, actptr->sr_name_len); + if (actptr->reginfo) { + netsnmp_unregister_handler(actptr->reginfo); + actptr->reginfo = NULL; + } 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); + (void) smux_list_add(&ActiveRegs, pasptr); free(actptr); + + reg = netsnmp_create_handler_registration("smux", + smux_handler, + pasptr->sr_name, + pasptr->sr_name_len, + HANDLER_CAN_RWRITE); + if (reg == NULL) { + snmp_log(LOG_ERR, "SMUX: cannot create new smux peer registration\n"); + pasptr->reginfo = NULL; + return; + } + if (netsnmp_register_handler(reg) != MIB_REGISTERED_OK) { + snmp_log(LOG_ERR, "SMUX: cannot register new smux peer\n"); + pasptr->reginfo = NULL; + return; + } + pasptr->reginfo = reg; } static void @@ -1373,8 +1456,6 @@ smux_snmp_process(int exact, /* * Send the query to the peer */ - smux_reqid++; - if (exact) type = SMUX_GET; else @@ -1757,6 +1838,7 @@ smux_peer_cleanup(int sd) { smux_reg *nrptr, *rptr, *rptr2; int i; + netsnmp_handler_registration *reg; /* * close the descriptor @@ -1781,15 +1863,30 @@ smux_peer_cleanup(int sd) rptr2 = rptr->sr_next; if (rptr->sr_fd == sd) { smux_list_detach(&ActiveRegs, rptr); - unregister_mib(rptr->sr_name, rptr->sr_name_len); + if (rptr->reginfo) { + netsnmp_unregister_handler(rptr->reginfo); + rptr->reginfo = NULL; + } if ((nrptr = smux_find_replacement(rptr->sr_name, rptr->sr_name_len)) != - NULL) { + NULL) { smux_list_detach(&PassiveRegs, nrptr); + reg = netsnmp_create_handler_registration("smux", + smux_handler, + nrptr->sr_name, + nrptr->sr_name_len, + HANDLER_CAN_RWRITE); + if (reg == NULL) { + snmp_log(LOG_ERR, "SMUX: cannot create new smux peer " + "registration\n"); + continue; + } + if (netsnmp_register_handler(reg) != MIB_REGISTERED_OK) { + snmp_log(LOG_ERR, "SMUX: cannot register new smux peer\n"); + continue; + } + nrptr->reginfo = reg; smux_list_add(&ActiveRegs, nrptr); - register_mib("smux", (struct variable *) - smux_variables, sizeof(struct variable2), - 1, nrptr->sr_name, nrptr->sr_name_len); } free(rptr); } diff -up net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.h.rhel net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.h --- net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.h.rhel 2012-07-31 14:13:21.893006290 +0200 +++ net-snmp-5.7.2.pre2/agent/mibgroup/smux/smux.h 2012-07-31 13:49:55.000000000 +0200 @@ -60,6 +60,7 @@ typedef struct _smux_reg { int sr_priority; /* priority of registration */ int sr_fd; /* descriptor of owner */ struct _smux_reg *sr_next; /* next one */ + netsnmp_handler_registration *reginfo; } smux_reg; extern void init_smux(void);