From: kostas <> Date: Sun, 22 Feb 1998 18:57:16 +0000 (+0000) Subject: Updated to cmu v1.8 + coded almost from scratch X-Git-Tag: SQUID_3_0_PRE1~4032 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=571c3b88dd021c80ba39a3fee22444ebc1a8590d;p=thirdparty%2Fsquid.git Updated to cmu v1.8 + coded almost from scratch --- diff --git a/src/snmp_agent.cc b/src/snmp_agent.cc index f9e7dd1d72..e0af9bff94 100644 --- a/src/snmp_agent.cc +++ b/src/snmp_agent.cc @@ -1,29 +1,3 @@ -/* - * Simple Network Management Protocol (RFC 1067). - * - */ -/*********************************************************** - Copyright 1988, 1989 by Carnegie Mellon University - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of CMU not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. -******************************************************************/ - #include "squid.h" #include "snmp.h" @@ -31,953 +5,769 @@ SOFTWARE. #include "asn1.h" #include "snmp_api.h" #include "snmp_client.h" +#include "snmp_vars.h" +#include "snmp_oidlist.h" +#include "cache_snmp.h" #include "mib.h" -#include "snmp_groupvars.h" - -void snmp_input(); -void snmp_trap(); -int create_identical(); -int parse_var_op_list(); - -struct pbuf *definitelyGetBuf(); -int get_community(); - -extern communityEntry *communities; -extern usecEntry *users; -extern viewEntry *views; -extern int maintenanceView; - -/* these can't be global in a multi-process router */ -u_char sid[SID_MAX_LEN + 1]; -int sidlen; -u_char *packet_end; - -struct snmp_session _session; -struct snmp_session *session = &_session; - -u_char _agentID[12] = -{0}; -u_long _agentBoots; -u_long _agentStartTime; -u_long _agentSize; - - -/* fwd: */ -static int check_auth(struct snmp_session *, u_char *, int, u_char *, int, usecEntry **); -static int bulk_var_op_list(u_char *, int, u_char *, int, int, int, long *); -static int goodValue(u_char, int, u_char, int); -static void setVariable(u_char *, u_char, int, u_char *, int); -/* from usec.c: */ -extern void increment_stat(); -extern void create_report(); -extern void md5Digest(); -extern int parse_parameters(); - -int -init_agent_auth(void) -{ - char hostname[256]; - struct hostent *hp; - FILE *f; - /* comes from snmpd.c: */ - - /* agentID is based on enterprise number and local IP address */ - /* not "settable, thus, if agentBoots=0xffffffff, then all keys should be changed */ - if (gethostname(hostname, sizeof(hostname)) != 0) { - fatal("snmpd: cannot get hostname"); - return -1; - } - if ((hp = gethostbyname(hostname)) == NULL) { - fatal("snmpd: cannot determine local hostname"); - return -1; - } - _agentID[3] = 35; /* BNR private enterprise number */ - xmemcpy(&_agentID[4], hp->h_addr, hp->h_length); - - if (Config.Snmp.agentInfo == NULL) { - debug(49, 1) ("init_agent_auth: WARNING: Config.Snmp.agentInfo == NULL\n"); - return -1; - } - if ((f = fopen(Config.Snmp.agentInfo, "r+")) == NULL) { - debug(49, 5) ("init_agent_auth: Agent not installed properly, cannot open '%s'\n", - Config.Snmp.agentInfo); - debug(49, 5) ("init_agent_auth: Create a empty file '%s'. This is used for\n", - Config.Snmp.agentInfo); - debug(49, 5) ("NV store of the agentBoots object.\n"); - return -1; - } - fscanf(f, "%ld", &_agentBoots); - _agentBoots++; - fseek(f, 0, 0); - fprintf(f, "%ld\n", _agentBoots); - fclose(f); +enum { HTTP_SVC, ICP_SVC, DNS_SVC }; +static struct snmp_pdu *snmp_agent_response(struct snmp_pdu *PDU); +struct snmp_session *Session; +extern StatCounters *CountHist; +extern int get_median_svc(int,int); - _agentStartTime = -time(NULL); +/* returns: + 2: no such object in this mib + 1: ok + 0: failed */ - _agentSize = SNMP_MAX_LEN; - - return 0; -} - -int -snmp_agent_parse(u_char * sn_data, - int length, - u_char * out_sn_data, - int *out_length, - u_long sourceip, /* possibly for authentication */ - long *ireqid) +int snmp_agent_parse(u_char *buf, int len, u_char *outbuf, int *outlen, + u_long from_addr, long * this_reqid) { - u_char msgtype, type; - long zero = 0; - long reqid, errstat, errindex, dummyindex; - u_char *out_auth, *out_header, *out_reqid; - u_char *startData = sn_data; - int startLength = length; - long version; - u_char *origsn_data = sn_data; - int origlen = length; - usecEntry *ue; - int ret = 0, packet_len; - - sidlen = SID_MAX_LEN; - sn_data = snmp_auth_parse(sn_data, &length, sid, &sidlen, &version); - if (sn_data == NULL) { - increment_stat(SNMP_STAT_ENCODING_ERRORS); - debug(49, 5) ("snmp_agent_parse: bad auth encoding\n"); - return 0; - } - if (version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2) { - increment_stat(SNMP_STAT_ENCODING_ERRORS); - debug(49, 5) ("snmp_agent_parse: wrong version\n"); -#ifdef linux - snmp_inbadversions++; -#endif - return 0; - } - if (version == SNMP_VERSION_2C || version == SNMP_VERSION_2) { - if (version == SNMP_VERSION_2) { - ret = check_auth(session, origsn_data, origlen, sn_data - sidlen, sidlen, &ue); - *out_length = (SNMP_MAX_LEN < session->MMS) ? SNMP_MAX_LEN : session->MMS; - session->MMS = SNMP_MAX_LEN; - - } else if (version == SNMP_VERSION_2C) { - ret = get_community(sid); - session->version = SNMP_VERSION_2C; - } - if (ret < 0) { - increment_stat(-ret); - if ((sn_data = asn_parse_header(sn_data, &length, &msgtype)) != NULL - && asn_parse_int(sn_data, &length, &type, &reqid, sizeof(reqid))) { - if (msgtype == REPORT_MSG) - return 0; - if (!(session->qoS & USEC_QOS_GENREPORT)) - return 0; - session->agentBoots = _agentBoots; - session->agentClock = _agentStartTime; - xmemcpy(session->agentID, _agentID, 12); - session->MMS = SNMP_MAX_LEN; - create_report(session, out_sn_data, out_length, -ret, reqid); - return 1; - } else { - debug(49, 5) ("snmp_agent_parse: asn_parse failed\n"); - return 0; - } - } else if (ret > 0) { - increment_stat(ret); - debug(49, 5) ("snmp_agent_parse: authorization failed ret=%d\n", ret); - return 0; - } - } else if (version == SNMP_VERSION_1) { - if ((ret = get_community(sid)) != 0) { - increment_stat(ret); - debug(49, 5) ("snmp_agent_parse: get_community failed\n"); - return 0; - } - session->version = SNMP_VERSION_1; - } else { - increment_stat(SNMP_STAT_ENCODING_ERRORS); - debug(49, 5) ("snmp_agent_parse : wrong version\n"); -#ifdef linux - snmp_inbadversions++; + struct snmp_pdu *PDU, *RespPDU; + u_char *Community; + int ret; + /* Now that we have the data, turn it into a PDU */ + PDU = snmp_pdu_create(0); + Community = snmp_parse(Session, PDU, buf, len); + if (Community == NULL) { + debug(49,8)("snmp_agent_parse: Community == NULL\n"); + + snmp_free_pdu(PDU); + return 0; + } +#if 0 + if (!community_check(Community)) { + xfree(Community); + /* Wrong community! XXXXX */ + } #endif - return 0; - } - sn_data = asn_parse_header(sn_data, &length, &msgtype); - if (sn_data == NULL) { - increment_stat(SNMP_STAT_ENCODING_ERRORS); - debug(49, 5) ("snmp_agent_parse: bad header\n"); - return 0; - } -#ifdef linux - /* XXX: increment by total number of vars at correct place: */ - snmp_intotalreqvars++; - if (msgtype == GET_REQ_MSG) - snmp_ingetrequests++; - if (msgtype == GETNEXT_REQ_MSG) - snmp_ingetnexts++; - if (msgtype == SET_REQ_MSG) - snmp_insetrequests++; + xfree(Community); + debug(49,5)("snmp_agent_parse: reqid=%d\n",PDU->reqid); + RespPDU = snmp_agent_response(PDU); + snmp_free_pdu(PDU); + if (RespPDU == NULL) { + debug(49,8)("snmp_agent_parse: RespPDU == NULL\n"); + return 2; + } + debug(49,8)("snmp_agent_parse: Response pdu (%x) errstat=%d reqid=%d.\n", + RespPDU,RespPDU->errstat,RespPDU->reqid); +#if 0 + if (RespPDU->variables) { + debug(49,8)("snmp_agent_parse: len=%d\n", RespPDU->variables->val_len); + } #endif + /* Encode it */ + ret = snmp_build(Session, RespPDU, outbuf, outlen); + /* XXXXX Handle failure */ + snmp_free_pdu(RespPDU); + return 1; +} - if (msgtype == GETBULK_REQ_MSG) { - if (session->version == SNMP_VERSION_1) { - debug(49, 5) ("snmp_agent_parse: getbulk but version 1\n"); - return 0; - } - } else if (msgtype != GET_REQ_MSG && msgtype != GETNEXT_REQ_MSG && msgtype != SET_REQ_MSG) { - debug(49, 5) ("snmp_agent_parse: unknown request type\n"); - return 0; - } - sn_data = asn_parse_int(sn_data, &length, &type, &reqid, sizeof(reqid)); - if (sn_data == NULL) { - increment_stat(SNMP_STAT_ENCODING_ERRORS); - debug(49, 5) ("snmp_agent_parse: bad parse of reqid\n"); - return 0; - } - sn_data = asn_parse_int(sn_data, &length, &type, &errstat, sizeof(errstat)); - if (sn_data == NULL) { - increment_stat(SNMP_STAT_ENCODING_ERRORS); - debug(49, 5) ("snmp_agent_parse: bad parse of errstat\n"); -#ifdef linux - snmp_inasnparseerrors++; -#endif - return 0; - } - sn_data = asn_parse_int(sn_data, &length, &type, &errindex, sizeof(errindex)); - if (sn_data == NULL) { - increment_stat(SNMP_STAT_ENCODING_ERRORS); - debug(49, 5) ("bad parse of errindex\n"); - return 0; - } - /* - * Now start cobbling together what is known about the output packet. - * The final lengths are not known now, so they will have to be recomputed - * later. - */ - - /* setup for response */ - time((time_t *) & session->agentTime); - session->agentClock = _agentStartTime; - session->agentBoots = _agentBoots; - xmemcpy(session->agentID, _agentID, 12); - - out_auth = out_sn_data; - out_header = snmp_auth_build(out_auth, out_length, session, 1, 0); - if (out_header == NULL) { - debug(49, 5) ("snmp_agent_parse: snmp_auth_build failed\n"); -#ifdef linux - snmp_inasnparseerrors++; -#endif - return 0; - } - out_reqid = asn_build_sequence(out_header, out_length, (u_char) GET_RSP_MSG, 0); - if (out_reqid == NULL) { - debug(49, 5) ("snmp_agent_parse; out_reqid == NULL\n"); - return 0; - } - type = (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER); - /* return identical request id */ - out_sn_data = asn_build_int(out_reqid, out_length, type, &reqid, sizeof(reqid)); - if (out_sn_data == NULL) { - debug(49, 5) ("snmp_agent_parse; build reqid failed\n"); - return 0; - } - /* assume that error status will be zero */ - out_sn_data = asn_build_int(out_sn_data, out_length, type, &zero, sizeof(zero)); - if (out_sn_data == NULL) { - debug(49, 5) ("snmp_agent_parse: build errstat failed\n"); - return 0; - } - /* assume that error index will be zero */ - out_sn_data = asn_build_int(out_sn_data, out_length, type, &zero, sizeof(zero)); - if (out_sn_data == NULL) { - debug(49, 5) ("snmp_agent_parse: build errindex failed\n"); - return 0; - } - if (msgtype == GETBULK_REQ_MSG) - errstat = bulk_var_op_list(sn_data, length, out_sn_data, *out_length, - errstat, errindex, &errindex); - else - errstat = parse_var_op_list(sn_data, length, out_sn_data, *out_length, - &errindex, msgtype, SNM_RESERVE1); - - if (errstat == SNMP_ERR_NOSUCHNAME) { - /* see if we have forwarding turned on */ - if (Config.Snmp.localPort != 0) { - *ireqid = reqid; - return 2; - } - } - if (msgtype == SET_REQ_MSG) { - if (errstat == SNMP_ERR_NOERROR) - errstat = parse_var_op_list(sn_data, length, out_sn_data, *out_length, - &errindex, msgtype, SNM_RESERVE2); - if (errstat == SNMP_ERR_NOERROR) { - /* - * SETS require 3-4 passes through the var_op_list. The first two - * passes verify that all types, lengths, and values are valid - * and may reserve resources and the third does the set and a - * fourth executes any actions. Then the identical GET RESPONSE - * packet is returned. - * If either of the first two passes returns an error, another - * pass is made so that any reserved resources can be freed. - */ - parse_var_op_list(sn_data, length, out_sn_data, *out_length, - &dummyindex, msgtype, SNM_COMMIT); - parse_var_op_list(sn_data, length, out_sn_data, *out_length, - &dummyindex, msgtype, SNM_ACTION); - if (create_identical(startData, out_auth, startLength, 0L, 0L)) { - *out_length = packet_end - out_auth; - return 1; - } - debug(49, 5) ("snmp_agent_parse: problem in ERR_NOERROR\n"); - return 0; - } else { - parse_var_op_list(sn_data, length, out_sn_data, *out_length, - &dummyindex, msgtype, SNM_FREE); - } - } - switch ((short) errstat) { - case SNMP_ERR_NOERROR: - /* re-encode the headers with the real lengths */ - *out_length = packet_end - out_header; - packet_len = *out_length; - out_sn_data = asn_build_sequence(out_header, out_length, GET_RSP_MSG, - packet_end - out_reqid); - if (out_sn_data != out_reqid) { - debug(49, 5) ("snmp_agent_parse: internal error: header\n"); - return 0; - } - *out_length = packet_end - out_auth; - out_sn_data = snmp_auth_build(out_auth, out_length, session, 1, packet_end - out_header); - *out_length = packet_end - out_auth; -#if 0 - /* packet_end is correct for old SNMP. This dichotomy needs - * to be fixed. */ - if (session->version == SNMP_VERSION_2) - packet_end = out_auth + packet_len; + +static struct snmp_pdu *snmp_agent_response(struct snmp_pdu *PDU) +{ + struct snmp_pdu *Answer = NULL; + variable_list *VarPtr, *VarNew = NULL; + variable_list **VarPtrP, **RespVars; + int index = 0; + oid_ParseFn *ParseFn; + +#ifdef DEBUG_SNMP + printf("Received a %d PDU\n", PDU->command); #endif - break; - case SNMP_ERR_TOOBIG: - snmp_intoobigs++; -#ifdef NOT_DONE - if (session->version == SNMP_VERSION_2) { - create_toobig(out_auth, *out_length, reqid, pi); - break; - } - /* else FALLTHRU */ + + /* Create a response */ + Answer = snmp_pdu_create(SNMP_PDU_RESPONSE); + if (Answer == NULL) + return(NULL); + Answer->reqid = PDU->reqid; + Answer->errindex = 0; + + if (PDU->command == SNMP_PDU_GET) { + + RespVars = &(Answer->variables); + /* Loop through all variables */ + for (VarPtrP = &(PDU->variables); + *VarPtrP; + VarPtrP = &((*VarPtrP)->next_variable)) { + VarPtr = *VarPtrP; + + index++; + + /* Find the parsing function for this variable */ + ParseFn = oidlist_Find(VarPtr->name, VarPtr->name_length); + + if (ParseFn == NULL) { + Answer->errstat = SNMP_ERR_NOSUCHNAME; + debug(49,5)("snmp_agent_response: No such oid. "); + } else + VarNew = (*ParseFn)(VarPtr, (long *)&(Answer->errstat)); + + /* Was there an error? */ + if ((Answer->errstat != SNMP_ERR_NOERROR) || + (VarNew == NULL)) { + Answer->errindex = index; + debug(49,5)("snmp_agent_parse: successful.\n"); + /* Just copy the rest of the variables. Quickly. */ + *RespVars = VarPtr; + *VarPtrP = NULL; + return(Answer); + } + + /* No error. Insert this var at the end, and move on to the next. + */ + *RespVars = VarNew; + RespVars = &(VarNew->next_variable); + } + + return(Answer); + } + + else if (PDU->command == SNMP_PDU_GETNEXT) { + oid *TmpOidName; + int TmpOidNameLen = 0; + + /* Find the next OID. */ + VarPtr = PDU->variables; + + ParseFn = oidlist_Next(VarPtr->name, VarPtr->name_length, + &(TmpOidName), (long *)&(TmpOidNameLen)); + + if (ParseFn == NULL) { + Answer->errstat = SNMP_ERR_NOSUCHNAME; +#ifdef DEBUG_SNMP + printf("No such oid: "); + print_oid(VarPtr->name, VarPtr->name_length); #endif - case SNMP_ERR_NOACCESS: - case SNMP_ERR_WRONGTYPE: - case SNMP_ERR_WRONGLENGTH: - case SNMP_ERR_WRONGENCODING: - case SNMP_ERR_WRONGVALUE: - case SNMP_ERR_NOCREATION: - case SNMP_ERR_INCONSISTENTVALUE: - case SNMP_ERR_RESOURCEUNAVAILABLE: - case SNMP_ERR_COMMITFAILED: - case SNMP_ERR_UNDOFAILED: - case SNMP_ERR_AUTHORIZATIONERROR: - case SNMP_ERR_NOTWRITABLE: - case SNMP_ERR_INCONSISTENTNAME: - case SNMP_ERR_NOSUCHNAME: - case SNMP_ERR_BADVALUE: - case SNMP_ERR_READONLY: - case SNMP_ERR_GENERR: - if (create_identical(startData, out_auth, startLength, errstat, - errindex)) { - *out_length = packet_end - out_auth; - return 1; - } - debug(49, 5) ("snmp_agent_parse: create_identical failed\n"); - return 0; - default: - debug(49, 5) ("snmp_agent_parse: hey, something's wrong\n"); - return 0; + } else { + xfree(VarPtr->name); + VarPtr->name = TmpOidName; + VarPtr->name_length = TmpOidNameLen; + VarNew = (*ParseFn)(VarPtr, (long *)&(Answer->errstat)); } - if (session->qoS & USEC_QOS_AUTH) { - md5Digest(out_auth, *out_length, out_sn_data - (session->contextLen + 16), - out_sn_data - (session->contextLen + 16)); - } - return 1; -} + /* Was there an error? */ + if (Answer->errstat != SNMP_ERR_NOERROR) { + Answer->errindex = 1; -/* - * Parse_var_op_list goes through the list of variables and retrieves each one, - * placing it's value in the output packet. In the case of a set request, - * if action is RESERVE, the value is just checked for correct type and - * value, and resources may need to be reserved. If the action is COMMIT, - * the variable is set. If the action is FREE, an error was discovered - * somewhere in the previous RESERVE pass, so any reserved resources - * should be FREE'd. - * If any error occurs, an error code is returned. - */ -int -parse_var_op_list(u_char * sn_data, - int length, - u_char * out_sn_data, - int out_length, - long *index, - int msgtype, - int action) -{ - u_char type; - oid var_name[MAX_NAME_LEN]; - int var_name_len, var_val_len; - u_char var_val_type, *var_val, statType; - u_char *statP; - int statLen = 0; - u_short acl; - int rw, exact, err; - int (*write_method) (); - u_char *headerP, *var_list_start; - int dummyLen; - u_char *getStatPtr(); - int noSuchObject; - - if (msgtype == SET_REQ_MSG) - rw = WRITE; - else - rw = READ; - if (msgtype == GETNEXT_REQ_MSG) { - exact = FALSE; + /* Just copy this variable */ + Answer->variables = VarPtr; + PDU->variables = NULL; } else { - exact = TRUE; - } - sn_data = asn_parse_header(sn_data, &length, &type); - if (sn_data == NULL) { - debug(49, 5) ("parse_var_op_list: not enough space for varlist\n"); - return PARSE_ERROR; - } - if (type != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { - debug(49, 5) ("parse_var_op_list: wrong type\n"); - return PARSE_ERROR; - } - headerP = out_sn_data; - out_sn_data = asn_build_sequence(out_sn_data, &out_length, - (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); - if (out_sn_data == (u_char *) NULL) { - debug(49, 5) ("parse_var_op_list: not enough space in output packet\n"); - return BUILD_ERROR; + Answer->variables = VarNew; } - var_list_start = out_sn_data; - - *index = 1; - while ((int) length > 0) { - /* parse the name, value pair */ - var_name_len = MAX_NAME_LEN; - sn_data = snmp_parse_var_op(sn_data, var_name, &var_name_len, &var_val_type, - &var_val_len, &var_val, (int *) &length); - if (sn_data == NULL) - return PARSE_ERROR; - /* now attempt to retrieve the variable on the local entity */ - debug(49, 5) ("snmp:before getStatPtr...\n"); - statP = getStatPtr(var_name, &var_name_len, &statType, &statLen, &acl, - exact, &write_method, session->version, &noSuchObject, - msgtype == SET_REQ_MSG ? session->writeView : session->readView); - if (session->version == SNMP_VERSION_1 && statP == NULL - && (msgtype != SET_REQ_MSG || !write_method)) { - debug(49, 5) ("parse_var_op_list: internal v1_error\n"); - return SNMP_ERR_NOSUCHNAME; - } - /* check if this variable is read-write (in the MIB sense). */ - if (msgtype == SET_REQ_MSG && acl != RWRITE) - return session->version == SNMP_VERSION_1 ? SNMP_ERR_NOSUCHNAME : SNMP_ERR_NOTWRITABLE; - - /* Its bogus to check here on getnexts - the whole packet shouldn't - * be dumped - this should should be the loop in getStatPtr - * luckily no objects are set unreadable. This can still be - * useful for sets to determine which are intrinsically writable */ - - if (msgtype == SET_REQ_MSG) { - if (write_method == NULL) { - if (statP != NULL) { - /* see if the type and value is consistent with this - * entity's variable */ - if (!goodValue(var_val_type, var_val_len, statType, - statLen)) { - if (session->version != SNMP_VERSION_1) - return SNMP_ERR_WRONGTYPE; /* poor approximation */ - else { - snmp_inbadvalues++; - return SNMP_ERR_BADVALUE; - } - } - /* actually do the set if necessary */ - if (action == SNM_COMMIT) - setVariable(var_val, var_val_type, var_val_len, - statP, statLen); - } else { - if (session->version != SNMP_VERSION_1) - return SNMP_ERR_NOCREATION; - else - return SNMP_ERR_NOSUCHNAME; - } - } else { - err = (*write_method) (action, var_val, var_val_type, - var_val_len, statP, var_name, - var_name_len); - - /* - * Map the SNMPv2 error codes to SNMPv1 error codes (RFC 2089). - */ - - if (session->version == SNMP_VERSION_1) { - switch (err) { - case SNMP_ERR_NOERROR: - /* keep the no-error error: */ - break; - case SNMP_ERR_WRONGVALUE: - case SNMP_ERR_WRONGENCODING: - case SNMP_ERR_WRONGTYPE: - case SNMP_ERR_WRONGLENGTH: - case SNMP_ERR_INCONSISTENTVALUE: - err = SNMP_ERR_BADVALUE; - break; - case SNMP_ERR_NOACCESS: - case SNMP_ERR_NOTWRITABLE: - case SNMP_ERR_NOCREATION: - case SNMP_ERR_INCONSISTENTNAME: - case SNMP_ERR_AUTHORIZATIONERROR: - err = SNMP_ERR_NOSUCHNAME; - break; - default: - err = SNMP_ERR_GENERR; - break; - } - } - if (err != SNMP_ERR_NOERROR) { - if (session->version == SNMP_VERSION_1) { - snmp_inbadvalues++; - } - return err; - } - } - } else { - /* retrieve the value of the variable and place it into the - * outgoing packet */ - if (statP == NULL) { - statLen = 0; - if (exact) { - if (noSuchObject == TRUE) { - statType = SNMP_NOSUCHOBJECT; - } else { - statType = SNMP_NOSUCHINSTANCE; - } - } else { - statType = SNMP_ENDOFMIBVIEW; - } - } - out_sn_data = snmp_build_var_op(out_sn_data, var_name, &var_name_len, - statType, statLen, statP, - &out_length); - if (out_sn_data == NULL) { - return SNMP_ERR_TOOBIG; - } - } - (*index)++; - } - if (msgtype != SET_REQ_MSG) { - /* save a pointer to the end of the packet */ - packet_end = out_sn_data; - - /* Now rebuild header with the actual lengths */ - dummyLen = packet_end - var_list_start; - if (asn_build_sequence(headerP, &dummyLen, - (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), - dummyLen) == NULL) { - return SNMP_ERR_TOOBIG; /* bogus error ???? */ - } - } - *index = 0; - return SNMP_ERR_NOERROR; + /* Done. Return this PDU */ + return(Answer); + } /* end SNMP_PDU_GETNEXT */ + +#ifdef DEBUG_SNMP + printf("Ignoring PDU %d\n", PDU->command); +#endif + snmp_free_pdu(Answer); + return(NULL); } -/* - * create a packet identical to the input packet, except for the error status - * and the error index which are set according to the input variables. - * Returns 1 upon success and 0 upon failure. - */ -int -create_identical(u_char * snmp_in, - u_char * snmp_out, - int snmp_length, - long errstat, - long errindex) +char private_community[]= "public"; + +int community_check(char *b) { - u_char *sn_data; - u_char type; - u_long dummy; - int length, headerLength; - u_char *headerPtr, *reqidPtr, *errstatPtr, *errindexPtr, *varListPtr; - - memcpy((char *) snmp_out, (char *) snmp_in, snmp_length); - length = snmp_length; - headerPtr = snmp_auth_parse(snmp_out, &length, sid, &sidlen, (long *) &dummy); - sid[sidlen] = 0; - if (headerPtr == NULL) - return 0; - reqidPtr = asn_parse_header(headerPtr, &length, (u_char *) & dummy); - if (reqidPtr == NULL) - return 0; - headerLength = length; - errstatPtr = asn_parse_int(reqidPtr, &length, &type, (long *) &dummy, sizeof dummy); /* request id */ - if (errstatPtr == NULL) - return 0; - errindexPtr = asn_parse_int(errstatPtr, &length, &type, (long *) &dummy, sizeof dummy); /* error status */ - if (errindexPtr == NULL) - return 0; - varListPtr = asn_parse_int(errindexPtr, &length, &type, (long *) &dummy, sizeof dummy); /* error index */ - if (varListPtr == NULL) - return 0; - - sn_data = asn_build_header(headerPtr, &headerLength, GET_RSP_MSG, headerLength); - if (sn_data != reqidPtr) - return 0; - length = snmp_length; - type = (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER); - sn_data = asn_build_int(errstatPtr, &length, type, &errstat, sizeof errstat); - if (sn_data != errindexPtr) - return 0; - sn_data = asn_build_int(errindexPtr, &length, type, &errindex, sizeof errindex); - if (sn_data != varListPtr) - return 0; - packet_end = snmp_out + snmp_length; - return 1; + return(!strcmp(b, private_community)); } -static int -check_auth(struct snmp_session *session, - u_char * sn_data, - int length, - u_char * pp, - int plen, - usecEntry ** ueret) +int init_agent_auth() { - usecEntry *ue; - Parameters params; - int ret; - - memset(session, 0, sizeof(*session)); - - *ueret = NULL; - - session->version = SNMP_VERSION_2; - - if ((ret = parse_parameters(pp, plen, ¶ms))) - return ret; - - /* setup session record for this packet */ - /* setup before any error detection so report may be generated if required */ - session->qoS = params.qoS; - xmemcpy(session->userName, params.userName, params.userLen); - session->userLen = params.userLen; - session->MMS = params.MMS; - session->contextLen = params.contextLen; - xmemcpy(session->contextSelector, params.contextSelector, params.contextLen); - - /* agentID must be my agentID */ - if (memcmp(_agentID, params.agentID, 12) != 0) - return -USEC_STAT_UNKNOWN_CONTEXT_SELECTORS; - - /* only support the contextSelector of "" */ - if (params.contextLen != 0) - return -USEC_STAT_UNKNOWN_CONTEXT_SELECTORS; - - /* lookup the user in my local configuration sn_datastore (LCD) */ - for (ue = users; ue; ue = ue->next) { - if (ue->userLen != params.userLen) - continue; - if (memcmp(ue->userName, params.userName, params.userLen) == 0) - break; - } - - /* if reached end of sn_datastore, user not found */ - if (ue == NULL) - return -USEC_STAT_UNKNOWN_USERNAMES; - - - /* verify that the requested qoS is supported by the userName */ - if ((u_char) (params.qoS & USEC_QOS_AUTHPRIV) > ue->qoS) - return -USEC_STAT_UNSUPPORTED_QOS; - - xmemcpy(session->authKey, ue->authKey, 16); - - /* check digest and timeliness if this is an auth message */ - if (params.qoS & USEC_QOS_AUTH) { - int upper, lower, agentTime; + Session = (struct snmp_session *)xmalloc(sizeof(struct snmp_session)); + if (Session == NULL) { + perror("malloc"); + return 3; + } + + Session->Version=SNMP_VERSION_1; + Session->authenticator = NULL; + Session->community = (u_char *)xstrdup("public"); + Session->community_len = 6; + return 1; +} - /* check the digest */ - xmemcpy(params.authDigestPtr, ue->authKey, 16); - md5Digest(sn_data, length, ue->authKey, params.authDigestPtr); - if (memcmp(params.authDigest, params.authDigestPtr, 16) != 0) - return -USEC_STAT_WRONG_DIGEST_VALUES; +/************************************************************************ - /* check timeliness */ - if (_agentBoots == 0xffffffff || _agentBoots != params.agentBoots) - return -USEC_STAT_NOT_IN_WINDOWS; + SQUID MIB Implementation - agentTime = _agentStartTime + time(NULL); - upper = agentTime + SNMP_MESSAGE_LIFETIME; - lower = agentTime - SNMP_MESSAGE_LIFETIME; - if (lower < 0) - lower = 0; - if (params.agentTime < lower || params.agentTime > upper) - return -USEC_STAT_NOT_IN_WINDOWS; + ************************************************************************/ - session->readView = ue->authReadView; - session->writeView = ue->authWriteView; - } else { - session->readView = ue->noauthReadView; - session->writeView = ue->noauthWriteView; - } +variable_list *snmp_basicFn(variable_list *Var, long *ErrP) +{ + variable_list *Answer; + char *pp; + + debug(49,5)("snmp_basicFn: Processing request with magic %d!\n",Var->name[7]); + + Answer = snmp_var_new(Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + + switch (Var->name[7]) { + case VERSION_DESCR: + case VERSION_ID: + pp = SQUID_VERSION; + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(pp); + Answer->val.string= (u_char *)xstrdup(pp); + break; + case UPTIME: + case SYSORLASTCHANGE: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = tvSubDsec(squid_start, current_time); + break; + case SYSCONTACT: + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(Config.adminEmail); + Answer->val.string= (u_char *)xstrdup(Config.adminEmail); + case SYSYSNAME: + if (( pp= Config.visibleHostname) == NULL) + pp=(char *)getMyHostname(); + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(pp); + Answer->val.string= (u_char *)xstrdup(pp); + break; + case SYSLOCATION: + pp = "Cyberspace"; + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(pp); + Answer->val.string= (u_char *)xstrdup(pp); + break; + case SYSSERVICES: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = 72; + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + debug(49,5)("snmp_basicFn: Done. returning a real value!\n"); + + return(Answer); +} - return 0; +variable_list *snmp_sysFn(variable_list *Var, long *ErrP) +{ + variable_list *Answer; + static fde *f=NULL; + int num=1,cnt=0; + static struct in_addr addr; + static long long_return; + + debug(49,5)("snmp_sysFn: Processing request with magic %d: \n",Var->name[8]); + print_oid(Var->name, Var->name_length); + + Answer = snmp_var_new(Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + + switch(Var->name[8]) { + case SYSVMSIZ: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = store_mem_size; + break; + case SYSSTOR: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = store_swap_size; + break; + case SYSFDTBL: + num=Var->name[11]; + debug(49,9)("snmp_sysFn: num=%d\n",num); + while (num && cnt < Squid_MaxFD) { + f = &fd_table[cnt++]; + if (!f->open) + continue; + num--; + } + if (num!=0 || !f) { + debug(49,9)("snmp_sysFn: no such name. %x\n",f); + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + switch (Var->name[10]) { + case SYS_FD_NUMBER: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer)= Var->name[11]; + break; + case SYS_FD_TYPE: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer)= f->type; + break; + case SYS_FD_TOUT: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer)= (long) (f->timeout_handler ? (f->timeout - squid_curtime)/ 60 : 0); + break; + case SYS_FD_NREAD: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer)= (long) f->bytes_read; + break; + case SYS_FD_NWRITE: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer)= (long) f->bytes_written; + break; + case SYS_FD_ADDR: + if (f->type != FD_SOCKET) + long_return = (long) 0; + else { + safe_inet_addr(f->ipaddr, &addr); + long_return = (long) addr.s_addr; + } + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = SMI_IPADDRESS; + *(Answer->val.integer)= (long) long_return; + break; + case SYS_FD_NAME: + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(f->desc); + Answer->val.string= (u_char *)xstrdup(f->desc); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + debug(49,5)("snmp_sysFn: Done. returning a real value!\n"); + return Answer; } -int -get_community(char *sessionid) +variable_list *snmp_confFn(variable_list *Var, long *ErrP) { - communityEntry *cp; - debug(49, 5) ("get_community: %s\n", sessionid); - for (cp = Config.Snmp.communities; cp; cp = cp->next) { - debug(49, 5) ("get_community: %s\n", cp->name); - if (!strcmp(cp->name, sessionid)) - break; + variable_list *Answer; + char *cp=NULL; + + debug(49,5)("snmp_confFn: Processing request with magic %d!\n",Var->name[8]); + + Answer = snmp_var_new(Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + + switch(Var->name[8]) { + case CONF_ADMIN: + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(Config.adminEmail); + Answer->val.string= (u_char *)xstrdup(Config.adminEmail); + break; + case CONF_UPTIME: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = tvSubDsec(squid_start, current_time); + break; + case CONF_STORAGE: + switch (Var->name[9]) { + case CONF_ST_MMAXSZ: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Mem.maxSize; + break; + case CONF_ST_MHIWM: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Mem.highWaterMark; + break; + case CONF_ST_MLOWM: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Mem.lowWaterMark; + break; + case CONF_ST_SWMAXSZ: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Swap.maxSize; + break; + case CONF_ST_SWHIWM: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Swap.highWaterMark; + break; + case CONF_ST_SWLOWM: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Swap.lowWaterMark; + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + break; + case CONF_WAIS_RHOST: + if (Config.Wais.relayHost) + cp = Config.Wais.relayHost; + else + cp = "None"; + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(cp); + Answer->val.string= (u_char *)xstrdup(cp); + break; + case CONF_WAIS_RPORT: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Wais.relayPort; + break; + case CONF_TIO: + switch (Var->name[9]) { + case CONF_TIO_RD: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Timeout.read; + break; + case CONF_TIO_CON: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Timeout.connect; + break; + case CONF_TIO_REQ: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Config.Timeout.request; + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + case CONF_LOG_LVL: + if (!(cp = Config.debugOptions)) + cp = "None"; + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(cp); + Answer->val.string= (u_char *)xstrdup(cp); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); } + return Answer; +} - if (cp == NULL) { - snmp_inbadcommunitynames++; - return SNMP_STAT_V1_BAD_COMMUNITY_NAMES; - } - memset(session, 0, sizeof(*session)); - session->community = (unsigned char *)sessionid; - session->community_len = strlen(sessionid); - session->readView = cp->readView; - session->writeView = cp->writeView; +variable_list *snmp_confPtblFn(variable_list *Var, long *ErrP) +{ + variable_list *Answer; + char *cp=NULL; + peer *p=NULL; + int cnt; + debug(49,5)("snmp_confPtblFn: peer %d requested!\n",Var->name[11]); + + Answer = snmp_var_new(Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + + p=Config.peers; + cnt=Var->name[11]; + debug(49,5)("snmp_confPtblFn: we want .x.%d\n",Var->name[10]); + while (--cnt) if (!(p=p->next)); + if (p==NULL) { + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + + switch (Var->name[10]) { + case CONF_PTBL_ID: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) Var->name[10]; + break; + case CONF_PTBL_NAME: + cp = p->host; + Answer->type = ASN_OCTET_STR; + Answer->val_len=strlen(cp); + Answer->val.string= (u_char *)xstrdup(cp); + break; + case CONF_PTBL_IP: + Answer->type = SMI_IPADDRESS; + Answer->val.integer = xmalloc(Answer->val_len); + Answer->val_len = sizeof(long); + *(Answer->val.integer) = (long) (p->in_addr.sin_addr.s_addr); + break; + case CONF_PTBL_HTTP: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) p->http_port; + break; + case CONF_PTBL_ICP: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) p->icp_port; + break; + case CONF_PTBL_TYPE: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) p->type; + break; + case CONF_PTBL_STATE: + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) neighborUp(p); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + return Answer; +} - return 0; +variable_list *snmp_prfSysFn(variable_list *Var, long *ErrP) +{ + variable_list *Answer; + static struct rusage rusage; + + debug(49,5)("snmp_prfSysFn: Processing request with magic %d!\n",Var->name[9]); + + Answer = snmp_var_new(Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + Answer->type = ASN_INTEGER; + + switch(Var->name[9]) { + case PERF_SYS_PF: + squid_getrusage(&rusage); + *(Answer->val.integer) = rusage_pagefaults(&rusage); + break; + case PERF_SYS_NUMR: + *(Answer->val.integer) = IOStats.Http.reads; + break; + case PERF_SYS_DEFR: + *(Answer->val.integer) = IOStats.Http.reads_deferred; + break; + case PERF_SYS_MEMUSAGE: + *(Answer->val.integer) = (long) statMemoryAccounted() >> 10; + break; + case PERF_SYS_CPUUSAGE: + squid_getrusage(&rusage); + *(Answer->val.integer) = (long) rusage_cputime(&rusage); + break; + case PERF_SYS_MAXRESSZ: + squid_getrusage(&rusage); + *(Answer->val.integer) = (long) rusage_maxrss(&rusage); + break; + case PERF_SYS_CURLRUEXP: + Answer->type=SMI_TIMETICKS; + *(Answer->val.integer) = (long) ((double) storeExpiredReferenceAge() / 86400.0); + break; + case PERF_SYS_CURUNLREQ: + *(Answer->val.integer) = (long) Counter.unlink.requests; + break; + case PERF_SYS_CURUNUSED_FD: + *(Answer->val.integer) = (long) Squid_MaxFD - Number_FD; + break; + case PERF_SYS_CURRESERVED_FD: + *(Answer->val.integer) = (long) Number_FD; + break; + case PERF_SYS_NUMOBJCNT: + *(Answer->val.integer) = (long) memInUse(MEM_STOREENTRY); + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + return Answer; } -static int -goodValue(u_char inType, int inLen, u_char actualType, int actualLen) +variable_list *snmp_prfPeerFn(variable_list *Var, long *ErrP) { - if (inLen > actualLen) - return FALSE; - return (inType == actualType); + variable_list *Answer; + peer *p=NULL; + int cnt; + debug(49,5)("snmp_prfPeerFn: Processing request with magic %d!\n",Var->name[9]); + + Answer = snmp_var_new(Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + + p=Config.peers; + cnt=Var->name[12]; + debug(49,5)("snmp_prfPeerFn: we want .%d.%d\n",Var->name[11],cnt); + while (--cnt) if (!(p=p->next)); + if (p==NULL) { + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + + Answer->type = SMI_COUNTER32; + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + + switch(Var->name[11]) { + case PERF_PEERSTAT_ID: + Answer->type= ASN_INTEGER; + *(Answer->val.integer) = Var->name[11]; + break; + case PERF_PEERSTAT_SENT: + *(Answer->val.integer) = p->stats.pings_sent; + break; + case PERF_PEERSTAT_PACKED: + *(Answer->val.integer) = p->stats.pings_acked; + break; + case PERF_PEERSTAT_FETCHES: + *(Answer->val.integer) = p->stats.fetches; + break; + case PERF_PEERSTAT_RTT: + Answer->type= ASN_INTEGER; + *(Answer->val.integer) = p->stats.rtt; + break; + case PERF_PEERSTAT_IGN: + *(Answer->val.integer) = p->stats.ignored_replies; + break; + case PERF_PEERSTAT_KEEPAL_S: + *(Answer->val.integer) = p->stats.n_keepalives_sent; + break; + case PERF_PEERSTAT_KEEPAL_R: + *(Answer->val.integer) = p->stats.n_keepalives_recv; + break; + default: + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + xfree(Answer->val.integer); + return(NULL); + } + return Answer; } -static void -setVariable(u_char * var_val, - u_char var_val_type, - int var_val_len, - u_char * statP, - int statLen) +variable_list *snmp_prfProtoFn(variable_list *Var, long *ErrP) { - int buffersize = 1000; - - switch (var_val_type) { - case ASN_INTEGER: - case COUNTER: - case GAUGE: - case TIMETICKS: - asn_parse_int(var_val, &buffersize, &var_val_type, (long *) statP, statLen); + variable_list *Answer; + + debug(49,5)("snmp_prfProtoFn: Processing request with magic %d!\n",Var->name[8]); + + Answer = snmp_var_new(Var->name, Var->name_length); + *ErrP = SNMP_ERR_NOERROR; + + if (Var->name[9]==1) { /* cacheProtoAggregateStats */ + Answer->type = SMI_COUNTER32; + Answer->val_len = sizeof(long); + Answer->val.integer = xmalloc(Answer->val_len); + switch(Var->name[10]) { + case PERF_PROTOSTAT_AGGR_HTTP_REQ: + *(Answer->val.integer) = (long) Counter.client_http.requests; break; - case ASN_OCTET_STR: - case IPADDRESS: - case OPAQUE: - asn_parse_string(var_val, &buffersize, &var_val_type, statP, &statLen); + case PERF_PROTOSTAT_AGGR_HTTP_HITS: + *(Answer->val.integer) = (long) Counter.client_http.hits; break; - case ASN_OBJECT_ID: - asn_parse_objid(var_val, &buffersize, &var_val_type, (oid *) statP, &statLen); + case PERF_PROTOSTAT_AGGR_HTTP_ERRORS: + *(Answer->val.integer) = (long) Counter.client_http.errors; break; - } + case PERF_PROTOSTAT_AGGR_ICP_S: + *(Answer->val.integer) = (long) Counter.icp.pkts_sent; + break; + case PERF_PROTOSTAT_AGGR_ICP_R: + *(Answer->val.integer) = (long) Counter.icp.pkts_recv; + break; + case PERF_PROTOSTAT_AGGR_ICP_SKB: + *(Answer->val.integer) = (long) Counter.icp.kbytes_sent.kb; + break; + case PERF_PROTOSTAT_AGGR_ICP_RKB: + *(Answer->val.integer) = (long) Counter.icp.kbytes_recv.kb; + break; + case PERF_PROTOSTAT_AGGR_KBYTES_IN: + *(Answer->val.integer) = (long) Counter.client_http.kbytes_in.kb; + break; + case PERF_PROTOSTAT_AGGR_KBYTES_OUT: + *(Answer->val.integer) = (long) Counter.client_http.kbytes_out.kb; + break; + case PERF_PROTOSTAT_AGGR_CURSWAP: + *(Answer->val.integer) = (long) store_swap_size; + break; + case PERF_PROTOSTAT_AGGR_HTTP_SVC_5: + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) get_median_svc(5, HTTP_SVC); + break; + case PERF_PROTOSTAT_AGGR_ICP_SVC_5: + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) get_median_svc(5, ICP_SVC); + break; + case PERF_PROTOSTAT_AGGR_DNS_SVC_5: + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) get_median_svc(5, DNS_SVC); + break; + case PERF_PROTOSTAT_AGGR_HTTP_SVC_60: + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) get_median_svc(60, HTTP_SVC); + break; + case PERF_PROTOSTAT_AGGR_ICP_SVC_60: + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) get_median_svc(60, ICP_SVC); + break; + case PERF_PROTOSTAT_AGGR_DNS_SVC_60: + Answer->type = ASN_INTEGER; + *(Answer->val.integer) = (long) get_median_svc(60, DNS_SVC); + break; + default: + xfree(Answer->val.integer); + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + } + else { + *ErrP = SNMP_ERR_NOSUCHNAME; + snmp_var_free(Answer); + return(NULL); + } + return Answer; } -struct repeater { - oid name[MAX_NAME_LEN]; - int length; -} repeaterList[20]; - -static int -bulk_var_op_list(u_char * sn_data, - int length, - u_char * out_sn_data, - int out_length, - int non_repeaters, - int max_repetitions, - long *index) +variable_list *snmp_dnsFn(variable_list *Var, long *ErrP) { - u_char type; - oid var_name[MAX_NAME_LEN]; - int var_name_len, var_val_len; - u_char var_val_type, *var_val, statType; - u_char *statP; - int statLen; - u_short acl; - int (*write_method) (); - u_char *headerP, *var_list_start; - int dummyLen; - u_char *getStatPtr(); - u_char *repeaterStart, *out_sn_data_save; - int repeatCount, repeaterLength, indexStart, out_length_save; - int full = FALSE; - int noSuchObject, useful; - int repeaterIndex, repeaterCount; - struct repeater *rl; - - if (non_repeaters < 0) - non_repeaters = 0; - max_repetitions = *index; - if (max_repetitions < 0) - max_repetitions = 0; - - sn_data = asn_parse_header(sn_data, &length, &type); - if (sn_data == NULL) { - debug(49, 5) ("bulk_var_op_list: not enough space for varlist\n"); - snmp_inasnparseerrors++; - return PARSE_ERROR; - } - if (type != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) { - debug(49, 5) ("bulk_var_op_list: wrong type\n"); - snmp_inasnparseerrors++; - return PARSE_ERROR; - } - headerP = out_sn_data; - out_sn_data = asn_build_sequence(out_sn_data, &out_length, - (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), 0); - if (out_sn_data == NULL) { - debug(49, 5) ("bulk_var_op_list: not enough space in output packet\n"); - return BUILD_ERROR; - } - var_list_start = out_sn_data; - - out_length -= 32; /* slop factor */ - *index = 1; - while ((int) length > 0 && non_repeaters > 0) { - /* parse the name, value pair */ - - var_name_len = MAX_NAME_LEN; - sn_data = snmp_parse_var_op(sn_data, var_name, &var_name_len, &var_val_type, - &var_val_len, &var_val, (int *) &length); - if (sn_data == NULL) - return PARSE_ERROR; - /* now attempt to retrieve the variable on the local entity */ - statP = getStatPtr(var_name, &var_name_len, &statType, &statLen, &acl, - FALSE, &write_method, session->version, &noSuchObject, session->readView); - - if (statP == NULL) - statType = SNMP_ENDOFMIBVIEW; - - /* save out_sn_data so this varbind can be removed if it goes over - * the limit for this packet */ - - /* retrieve the value of the variable and place it into the outgoing packet */ - out_sn_data = snmp_build_var_op(out_sn_data, var_name, &var_name_len, - statType, statLen, statP, - &out_length); - if (out_sn_data == NULL) { - return SNMP_ERR_TOOBIG; /* ??? */ - } - (*index)++; - non_repeaters--; - } - - repeaterStart = out_sn_data; - indexStart = *index; /* index on input packet */ - - repeaterCount = 0; - rl = repeaterList; - useful = FALSE; - while ((int) length > 0) { - /* parse the name, value pair */ - rl->length = MAX_NAME_LEN; - sn_data = snmp_parse_var_op(sn_data, rl->name, &rl->length, - &var_val_type, &var_val_len, &var_val, - (int *) &length); - if (sn_data == NULL) { - snmp_inasnparseerrors++; - return PARSE_ERROR; - } - /* now attempt to retrieve the variable on the local entity */ - statP = getStatPtr(rl->name, &rl->length, &statType, &statLen, - &acl, FALSE, &write_method, session->version, &noSuchObject, session->readView); - if (statP == NULL) - statType = SNMP_ENDOFMIBVIEW; - else - useful = TRUE; - - out_sn_data_save = out_sn_data; - out_length_save = out_length; - /* retrieve the value of the variable and place it into the - * outgoing packet */ - out_sn_data = snmp_build_var_op(out_sn_data, rl->name, &rl->length, - statType, statLen, statP, - &out_length); - if (out_sn_data == NULL) { - out_sn_data = out_sn_data_save; - out_length = out_length_save; - full = TRUE; - } - (*index)++; - repeaterCount++; - rl++; - } - repeaterLength = out_sn_data - repeaterStart; - if (!useful) - full = TRUE; - - for (repeatCount = 1; repeatCount < max_repetitions; repeatCount++) { - sn_data = repeaterStart; - length = repeaterLength; - *index = indexStart; - repeaterStart = out_sn_data; - useful = FALSE; - repeaterIndex = 0; - rl = repeaterList; - while ((repeaterIndex++ < repeaterCount) > 0 && !full) { - /* now attempt to retrieve the variable on the local entity */ - statP = getStatPtr(rl->name, &rl->length, &statType, &statLen, - &acl, FALSE, &write_method, session->version, &noSuchObject, session->readView); - if (statP == NULL) - statType = SNMP_ENDOFMIBVIEW; - else - useful = TRUE; - - out_sn_data_save = out_sn_data; - out_length_save = out_length; - /* retrieve the value of the variable and place it into the - * Outgoing packet */ - out_sn_data = snmp_build_var_op(out_sn_data, rl->name, &rl->length, statType, statLen, statP, &out_length); - if (out_sn_data == NULL) { - out_sn_data = out_sn_data_save; - out_length = out_length_save; - full = TRUE; - repeatCount = max_repetitions; - } - (*index)++; - rl++; - } - repeaterLength = out_sn_data - repeaterStart; - if (!useful) - full = TRUE; - } - packet_end = out_sn_data; + debug(49,5)("snmp_dnsFn: Processing request with magic %d!\n",Var->name[9]); + if (Var->name[9] == NET_DNS_IPCACHE) + return snmp_ipcacheFn(Var,ErrP); + if (Var->name[9] == NET_DNS_FQDNCACHE) + return snmp_fqdncacheFn(Var,ErrP); - /* Now rebuild header with the actual lengths */ - dummyLen = out_sn_data - var_list_start; - if (asn_build_sequence(headerP, &dummyLen, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), dummyLen) == NULL) { - return SNMP_ERR_TOOBIG; /* bogus error ???? */ - } - *index = 0; - return SNMP_ERR_NOERROR; + return NULL; }