]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Squid SNMP code rewrite
authorglenn <>
Thu, 12 Nov 1998 03:04:09 +0000 (03:04 +0000)
committerglenn <>
Thu, 12 Nov 1998 03:04:09 +0000 (03:04 +0000)
13 files changed:
src/Makefile.in
src/acl.cc
src/cache_cf.cc
src/cf.data.pre
src/cf_gen.cc
src/client_side.cc
src/enums.h
src/main.cc
src/protos.h
src/snmp_agent.cc
src/snmp_core.cc
src/structs.h
src/typedefs.h

index 77780e4f084a32c1eea3cca7c24a7438f29a2dc6..fb73603309a7fda230039827a3c3022e6443980d 100644 (file)
@@ -1,7 +1,7 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.in,v 1.161 1998/10/10 14:57:36 wessels Exp $
+#  $Id: Makefile.in,v 1.162 1998/11/11 20:04:09 glenn Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
@@ -173,10 +173,7 @@ OBJS               = \
 
 SNMP_OBJS      = \
                snmp_core.o \
-                snmp_oidlist.o \
-                snmp_agent.o  \
-               snmp_config.o \
-               snmp_auth.o
+                snmp_agent.o
 
 HTCP_OBJS      = htcp.o
 
index 6a4743b799a363c2965160fec360674cb55dfa75..002240c757ae1c8755f6d7114ef08119f600ab3d 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: acl.cc,v 1.185 1998/10/13 23:33:29 wessels Exp $
+ * $Id: acl.cc,v 1.186 1998/11/11 20:04:10 glenn Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -46,7 +46,6 @@ static void aclParseWordList(void *curlist);
 static void aclParseProtoList(void *curlist);
 static void aclParseMethodList(void *curlist);
 static void aclParseTimeSpec(void *curlist);
-static void aclParseSnmpComm(void *curlist);
 static void aclParseIntRange(void *curlist);
 static char *strtokFile(void);
 static void aclDestroyAclList(acl_list * list);
@@ -61,6 +60,7 @@ static int aclMatchIdent(wordlist * data, const char *ident);
 static int aclMatchIp(void *dataptr, struct in_addr c);
 static int aclMatchDomainList(void *dataptr, const char *);
 static int aclMatchIntegerRange(intrange * data, int i);
+static int aclMatchWordList(wordlist *, const char *);
 static squid_acl aclStrToType(const char *s);
 static int decode_addr(const char *, struct in_addr *, struct in_addr *);
 static void aclCheck(aclCheck_t * checklist);
@@ -174,8 +174,10 @@ aclStrToType(const char *s)
        return ACL_SRC_ASN;
     if (!strcmp(s, "dst_as"))
        return ACL_DST_ASN;
+#if SQUID_SNMP
     if (!strcmp(s, "snmp_community"))
-       return ACL_SNMP_COMM;
+       return ACL_SNMP_COMMUNITY;
+#endif
     if (!strcmp(s, "src_rtt"))
        return ACL_NETDB_SRC_RTT;
 #if USE_ARP_ACL
@@ -222,8 +224,10 @@ aclTypeToStr(squid_acl type)
        return "src_as";
     if (type == ACL_DST_ASN)
        return "dst_as";
-    if (type == ACL_SNMP_COMM)
+#if SQUID_SNMP
+    if (type == ACL_SNMP_COMMUNITY)
        return "snmp_community";
+#endif
     if (type == ACL_NETDB_SRC_RTT)
        return "src_rtt";
 #if USE_ARP_ACL
@@ -639,23 +643,6 @@ aclParseProxyAuth(void *data)
     return;
 }
 
-static void
-aclParseSnmpComm(void *data)
-{
-    acl_snmp_comm **q = data;
-    acl_snmp_comm *p;
-    char *t;
-    t = strtok(NULL, w_space);
-    if (t) {
-       p = xcalloc(1, sizeof(acl_snmp_comm));
-       p->name = xstrdup(t);
-       p->community = NULL;
-       *q = p;
-    }
-    t = strtok(NULL, w_space);
-    return;
-}
-
 void
 aclParseAclLine(acl ** head)
 {
@@ -744,9 +731,11 @@ aclParseAclLine(acl ** head)
     case ACL_PROXY_AUTH:
        aclParseProxyAuth(&A->data);
        break;
-    case ACL_SNMP_COMM:
-       aclParseSnmpComm(&A->data);
+#if SQUID_SNMP
+    case ACL_SNMP_COMMUNITY:
+       aclParseWordList(&A->data);
        break;
+#endif
 #if USE_ARP_ACL
     case ACL_SRC_ARP:
        aclParseArpList(&A->data);
@@ -1150,6 +1139,19 @@ aclMatchTime(acl_time_data * data, time_t when)
     return data->weekbits & (1 << tm.tm_wday) ? 1 : 0;
 }
 
+static int
+aclMatchWordList(wordlist * w, const char *community)
+{
+    debug(28, 3) ("aclMatchWordList: looking for '%s'\n", community);
+    while (w != NULL) {
+       debug(28, 3) ("aclMatchWordList: checking '%s'\n", w->key);
+       if (!strcmp(w->key, community))
+           return 1;
+       w = w->next;
+    }
+    return 0;
+}
+
 static int
 aclMatchAcl(acl * ae, aclCheck_t * checklist)
 {
@@ -1283,8 +1285,10 @@ aclMatchAcl(acl * ae, aclCheck_t * checklist)
            return 0;
        }
        /* NOTREACHED */
-    case ACL_SNMP_COMM:
-       return asnMatchIp(ae->data, checklist->src_addr);
+#if SQUID_SNMP
+    case ACL_SNMP_COMMUNITY:
+       return aclMatchWordList(ae->data, checklist->snmp_community);
+#endif
     case ACL_SRC_ASN:
        return asnMatchIp(ae->data, checklist->src_addr);
     case ACL_DST_ASN:
@@ -1614,6 +1618,9 @@ aclDestroyAcls(acl ** head)
            splay_destroy(a->data, xfree);
            break;
        case ACL_USER:
+#if SQUID_SNMP
+       case ACL_SNMP_COMMUNITY:
+#endif
            wordlistDestroy((wordlist **) & a->data);
            break;
        case ACL_TIME:
@@ -1985,6 +1992,9 @@ aclDumpGeneric(const acl * a)
     case ACL_SRC_DOMAIN:
     case ACL_DST_DOMAIN:
     case ACL_USER:
+#if SQUID_SNMP
+    case ACL_SNMP_COMMUNITY:
+#endif
        return aclDumpDomainList(a->data);
        break;
     case ACL_TIME:
index 1c8a6cfbb939ce68870b50b8b4f2ee3c302a70b5..5fc75fdad577e598b37d597e721b1f064b0ffb5b 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: cache_cf.cc,v 1.308 1998/10/14 21:11:55 wessels Exp $
+ * $Id: cache_cf.cc,v 1.309 1998/11/11 20:04:12 glenn Exp $
  *
  * DEBUG: section 3     Configuration File Parsing
  * AUTHOR: Harvest Derived
@@ -64,10 +64,6 @@ static int parseTimeUnits(const char *unit);
 static void parseTimeLine(time_t * tptr, const char *units);
 static void parse_string(char **);
 static void parse_wordlist(wordlist **);
-#if SQUID_SNMP
-/* sigh, stringlist is only used for SNMP stuff now */
-static void parse_stringlist(wordlist **);
-#endif
 static void default_all(void);
 static void defaults_if_none(void);
 static int parse_line(char *);
@@ -447,31 +443,6 @@ free_acl(acl ** ae)
     aclDestroyAcls(ae);
 }
 
-#if SQUID_SNMP
-
-static void
-dump_snmp_access(StoreEntry * entry, const char *name, communityEntry * Head)
-{
-    acl_list *l;
-    communityEntry *cp;
-    acl_access *head;
-
-    for (cp = Head; cp; cp = cp->next) {
-       head = cp->acls;
-       while (head != NULL) {
-           for (l = head->acl_list; l != NULL; l = l->next) {
-               storeAppendPrintf(entry, "%s %s %s %s%s\n",
-                   name, cp->name,
-                   head->allow ? "Allow" : "Deny",
-                   l->op ? null_string : "!",
-                   l->acl->name);
-           }
-           head = head->next;
-       }
-    }
-}
-#endif
-
 static void
 dump_acl_access(StoreEntry * entry, const char *name, acl_access * head)
 {
@@ -490,39 +461,6 @@ dump_acl_access(StoreEntry * entry, const char *name, acl_access * head)
     }
 }
 
-#if SQUID_SNMP
-
-static void
-parse_snmp_access(communityEntry ** head)
-{
-    char *t = NULL;
-    communityEntry *cp;
-/* This is tricky: we need to define the communities here, assuming that 
- * communities and the MIB have already been defined */
-
-    if (!snmpInitConfig()) {
-       debug(15, 0) ("parse_snmp_access: Access lists NOT defined.\n");
-       return;
-    }
-    t = strtok(NULL, w_space);
-    for (cp = *head; cp; cp = cp->next)
-       if (!strcmp(t, cp->name)) {
-           aclParseAccessLine(&cp->acls);
-           return;
-       }
-    debug(15, 0) ("parse_snmp_access: Unknown community %s!\n", t);
-}
-
-static void
-free_snmp_access(communityEntry ** Head)
-{
-    communityEntry *cp;
-
-    for (cp = *Head; cp; cp = cp->next)
-       aclDestroyAccessList(&cp->acls);
-}
-#endif
-
 static void
 parse_acl_access(acl_access ** head)
 {
@@ -1393,18 +1331,6 @@ check_null_wordlist(wordlist * w)
     return w == NULL;
 }
 
-#if SQUID_SNMP
-static void
-parse_stringlist(wordlist ** list)
-{
-    char *token;
-    while ((token = strtok(NULL, null_string)))
-       wordlistAdd(list, token);
-}
-#define free_stringlist free_wordlist
-#define dump_stringlist dump_wordlist
-#endif /* SQUID_SNMP */
-
 #define free_wordlist wordlistDestroy
 
 #define free_uri_whitespace free_int
index 07b6b8af0fcbcabe9725dfdb44b7886cc691cf63..ba0a6e1d347e4f0f3fa83486e2c0043e428535fa 100644 (file)
@@ -1,6 +1,6 @@
 
 #
-# $Id: cf.data.pre,v 1.122 1998/10/14 21:11:57 wessels Exp $
+# $Id: cf.data.pre,v 1.123 1998/11/11 20:04:12 glenn Exp $
 #
 #
 # SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -1393,6 +1393,11 @@ DOC_START
          # needed during ACL checking the username is NOT logged
          # in access.log.
 
+       acl aclname snmp_community string ...
+         # Example:
+         # 
+         #     acl snmppublic snmp_community public
+
 acl manager proto cache_object
 acl localhost src 127.0.0.1/255.255.255.255
 acl all src 0.0.0.0/0.0.0.0
@@ -2283,19 +2288,6 @@ DOC_START
 snmp_port 3401
 DOC_END
 
-NAME: snmp_do_queueing
-TYPE: onoff
-LOC: Config.Snmp.do_queueing
-DEFAULT: on
-IFDEF: SQUID_SNMP
-DOC_START
-       If disabled, snmp packets will not be queued but delivered
-       immediately. This could be useful when you want to monitor a
-       cache in trouble, but this could also make Squid block, slowing
-       connections and possibly worsening the cache status.
-snmp_do_queueing on
-DOC_END
-
 NAME: forward_snmpd_port
 TYPE: ushort
 LOC: Config.Snmp.localPort
@@ -2317,73 +2309,16 @@ DOC_START
 forward_snmpd_port 0
 DOC_END
 
-NAME: snmp_mib_path
-TYPE: string
-LOC: Config.Snmp.mibPath
-DEFAULT: @DEFAULT_MIB_PATH@
-IFDEF: SQUID_SNMP
-DOC_START
-       The location of Squid's mib.
-snmp_mib_path @DEFAULT_MIB_PATH@
-DOC_END
-
-NAME: trap_sink
-TYPE: string
-LOC: Config.Snmp.trap_sink
-DEFAULT: 127.0.0.1
-IFDEF: SQUID_SNMP
-DOC_START
-       Hostname or ip address of trap sink for snmp
-trap_sink 127.0.0.1
-DOC_END
-
-NAME: snmp_trap_community
-TYPE: string
-LOC: Config.Snmp.trap_community
-DEFAULT: public
-IFDEF: SQUID_SNMP
-DOC_START
-       Community name for traps.
-snmp_trap_community public
-DOC_END
-
-NAME: snmp_enable_authen_traps
-TYPE: onoff
-LOC: Config.Snmp.conf_authtraps
-DEFAULT: off
-IFDEF: SQUID_SNMP
-DOC_START
-       Enable SNMP authenticated traps. Set to 'off' or 'on'.
-snmp_enable_authen_traps off
-DOC_END
-
-NAME: snmp_agent_conf
-TYPE: stringlist
-LOC: Config.Snmp.snmpconf
+NAME: snmp_access
+TYPE: acl_access
+LOC: Config.accessList.snmp
 DEFAULT: none
 IFDEF: SQUID_SNMP
 DOC_START
-       Define snmp views, users and communities 
-       Example:
-               snmp_agent_conf view all .1.3.6 included
-               snmp_agent_conf view squid .1.3.6 included
-               snmp_agent_conf user squid - all all public
-               snmp_agent_conf user all all all all  squid
-               snmp_agent_conf community public squid squid
-               snmp_agent_conf community readwrite all all
-DOC_END
+       Allowing or denying access to the SNMP port.
+       usage:
 
-NAME: snmp_acl
-TYPE: snmp_access
-LOC: Config.Snmp.communities
-DEFAULT: none
-IFDEF: SQUID_SNMP
-DOC_START
-       Define access controls per community:
-       snmp_access communityname allow|deny [!]aclname ...
-       Example:
-               snmp_acl public allow adminsubnet
-               snmp_acl public deny all
+       snmp_access allow|deny [!]aclname ...
 DOC_END
 
 NAME: snmp_incoming_address
index 0844ce317543ad3e66cc98afab18e165ee1aeaac..21c54696c5067b1727b25a7695b62fff9770727c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: cf_gen.cc,v 1.27 1998/08/21 09:15:43 wessels Exp $
+ * $Id: cf_gen.cc,v 1.28 1998/11/11 20:04:13 glenn Exp $
  *
  * DEBUG: none
  * AUTHOR: Max Okumoto
 #include <assert.h>
 #endif
 
-#if SQUID_SNMP
-#include "snmp.h"
-#endif
-
 #define MAX_LINE       1024    /* longest configuration line */
 #define _PATH_PARSER           "cf_parser.c"
 #define _PATH_SQUID_CONF       "squid.conf"
index dc148399dd395e116daf7c464c8381b26e8c0f31..772b1f785c753180c33bb4b37e258dcf7247a9bd 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.420 1998/10/19 06:15:29 rousskov Exp $
+ * $Id: client_side.cc,v 1.421 1998/11/11 20:04:14 glenn Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -1950,6 +1950,7 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
        return parseHttpRequestAbort(conn, "error:missing-http-ident");
 #endif
     } else {
+debug(0, 0) ("parseHttpRequest: VER is {%s}\n", token);
        http_ver = (float) atof(token + 5);
     }
 
index fcbe91c7c113bf7615ccd106bf3ebd6457f1ad7a..4470f4f31ceef87586084b361ded8b7b08d4cd07 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: enums.h,v 1.135 1998/10/12 21:40:57 wessels Exp $
+ * $Id: enums.h,v 1.136 1998/11/11 20:04:15 glenn Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -105,7 +105,7 @@ typedef enum {
     ACL_SRC_ASN,
     ACL_DST_ASN,
     ACL_SRC_ARP,
-    ACL_SNMP_COMM,
+    ACL_SNMP_COMMUNITY,
     ACL_NETDB_SRC_RTT,
     ACL_ENUM_MAX
 } squid_acl;
index 3452e85ad1bb09341eee610c02d4ca016e21c844..078b0ceb082a2c9a565c5db3a690cbbccd55e3d1 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: main.cc,v 1.274 1998/10/21 06:54:19 wessels Exp $
+ * $Id: main.cc,v 1.275 1998/11/11 20:04:16 glenn Exp $
  *
  * DEBUG: section 1     Startup and Main Loop
  * AUTHOR: Harvest Derived
@@ -416,6 +416,7 @@ mainInitialize(void)
 #ifdef SQUID_SNMP
     snmpInit();
 #endif
 
 #if MALLOC_DBG
     malloc_debug(0, malloc_debug_level);
index f34852011875482ab344ff51ba8617cdaf380e2e..c13f9e9003dd44eb1e00d202679ebbebd0fa92f7 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: protos.h,v 1.283 1998/10/23 21:53:32 glenn Exp $
+ * $Id: protos.h,v 1.284 1998/11/11 20:04:17 glenn Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -478,15 +478,23 @@ extern PF httpAccept;
 #ifdef SQUID_SNMP
 extern PF snmpHandleUdp;
 extern void snmpInit(void);
-extern int snmpInitConfig(void);
 extern void snmpConnectionOpen(void);
 extern void snmpConnectionShutdown(void);
 extern void snmpConnectionClose(void);
-extern int snmpCreateView(char **);
-extern int snmpCreateUser(char **);
-extern int snmpCreateCommunity(char **);
-extern void snmpTokenize(char *, char **, int);
-extern int snmpCompare(oid * name1, int len1, oid * name2, int len2);
+extern void snmpDebugOid(int lvl, oid * Name, snint Len);
+extern void addr2oid(struct in_addr addr, oid * Dest);
+extern struct in_addr* oid2addr(oid * id); 
+variable_list *snmp_basicFn(variable_list *, snint *);
+variable_list *snmp_confFn(variable_list *, snint *);
+variable_list *snmp_sysFn(variable_list *, snint *);
+variable_list *snmp_prfSysFn(variable_list *, snint *);
+variable_list *snmp_prfProtoFn(variable_list *, snint *);
+variable_list *snmp_prfPeerFn(variable_list *, snint *);
+variable_list *snmp_netIpFn(variable_list *, snint *);
+variable_list *snmp_netFqdnFn(variable_list *, snint *);
+variable_list *snmp_netDnsFn(variable_list *, snint *);
+variable_list *snmp_meshPtblFn(variable_list *, snint *);
+variable_list *snmp_meshCtblFn(variable_list *, snint *);
 #endif /* SQUID_SNMP */
 
 extern void icpHandleIcpV3(int, struct sockaddr_in, char *, int);
index 9b9d87a8a30ba7827fc19013d45e4d0966677c9c..e7cf55dbdb30bc2b50f53a9d873ae378ae92fab9 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: snmp_agent.cc,v 1.58 1998/09/29 16:33:49 wessels Exp $
+ * $Id: snmp_agent.cc,v 1.59 1998/11/11 20:04:18 glenn Exp $
  *
  * DEBUG: section 49     SNMP Interface
  * AUTHOR: Kostas Anagnostakis
 
 
 #include "squid.h"
-
-#include "snmp.h"
-#include "snmp_impl.h"
-#include "asn1.h"
-#include "snmp_api.h"
-#include "snmp_vars.h"
-#include "snmp_oidlist.h"
 #include "cache_snmp.h"
 
 extern StatCounters *snmpStatGet(int);
 
-
 /************************************************************************
 
  SQUID MIB Implementation
index 084c1b84b443cce5873320fc78ea55f133cfed24..8dd09f1fcf097a3ffa63dde1a9888fbdfcf7024f 100644 (file)
@@ -1,8 +1,8 @@
 /*
- * $Id: snmp_core.cc,v 1.12 1998/09/29 16:33:51 wessels Exp $
+ * $Id: snmp_core.cc,v 1.13 1998/11/11 20:04:19 glenn Exp $
  *
  * DEBUG: section 49    SNMP support
- * AUTHOR: Kostas Anagnostakis
+ * AUTHOR: Glenn Chisholm
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  * ----------------------------------------------------------
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
  *  (at your option) any later version.
- *  
+ *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
- *  
+ *
  *  You should have received a copy of the GNU General Public License
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  *
  */
-
-/**********************************************************************
- *
- *           Copyright 1996 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 SHAL
- * 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.
- * 
- * Author: Ryan Troll <ryan+@andrew.cmu.edu>
- * 
- **********************************************************************/
-
-
 #include "squid.h"
-
 #include "cache_snmp.h"
-#include "squid_mib.h"
 
 #define SNMP_REQUEST_SIZE 4096
 #define MAX_PROTOSTAT 5
 
-int snmp_dump_packet;
-void *users, *communities;
-
-static struct sockaddr_in local_snmpd;
-static int snmp_init_config = 0;
-struct snmp_session *Session;
-struct snmp_pdu *snmpAgentResponse(struct snmp_pdu *PDU);
-
-void snmpFwd_insertPending(struct sockaddr_in *, long);
-int snmpFwd_removePending(struct sockaddr_in *, long);
-
-extern void (*snmplib_debug_hook) (int, char *);
-static void snmpSnmplibDebug(int lvl, char *buf);
+struct _mib_tree_entry {
+       oid     *name;
+       int     len;
+       oid_ParseFn *parsefunction;
+       int     children;
+       struct _mib_tree_entry **leaves;
+       struct _mib_tree_entry *parent;
+};
 
-struct snmpUdpData {
+struct _snmpUdpData {
     struct sockaddr_in address;
     void *msg;
     int len;
-    struct snmpUdpData *next;
+    struct _snmpUdpData *next;
 };
 
-typedef struct snmpUdpData snmpUdpData;
-
-struct snmpFwdQueue {
-    struct sockaddr_in addr;
-    long req_id;
-    time_t req_time;
-    struct snmpFwdQueue *next;
-};
+typedef struct _snmpUdpData snmpUdpData;
+typedef struct _mib_tree_entry mib_tree_entry;
 
-struct snmpFwdQueue *snmpHead = NULL;
+mib_tree_entry *mib_tree_head;
+snmpUdpData *snmpUdpHead = NULL;
+snmpUdpData *snmpUdpTail = NULL;
 
-struct snmpUdpData *snmpUdpHead = NULL;
-struct snmpUdpData *snmpUdpTail = NULL;
+extern void (*snmplib_debug_hook) (int, char *);
 
-void snmpUdpReply(int, void *);
-void snmpAppendUdp(snmpUdpData *);
-void snmpUdpSend(int, const struct sockaddr_in *, void *, int);
+static void snmpDecodePacket(snmp_request_t * rq);
+static void snmpConstructReponse(snmp_request_t * rq, struct snmp_session *Session);
+static struct snmp_pdu* snmpAgentResponse(struct snmp_pdu *PDU);
 
-/* now include mib location definitions
- * and magic numbers */
+static void snmpUdpSend(int, const struct sockaddr_in *, void *, int);
+static void snmpUdpReply(int, void *);
+static void snmpAppendUdp(snmpUdpData *);
 
-#include "cache_snmp.h"
 
+static mib_tree_entry* snmpAddNode(oid *name, int len, oid_ParseFn *parsefunction, int children, ...);
+static oid_ParseFn *snmpTreeNext(oid *Current, snint CurrentLen, oid **Next, snint *NextLen);
+static mib_tree_entry* snmpTreeEntry(oid entry, snint len, mib_tree_entry *current);
 
-static void
-snmpSnmplibDebug(int lvl, char *buf)
-{
-    debug(49, lvl) ("%s", buf);
-}
+static oid* snmpCreateOid(int length, ...);
+static oid* snmpOidDup(oid * A, snint ALen);                       
+static void snmpSnmplibDebug(int lvl, char *buf);
 
-void
-snmpHandleUdp(int sock, void *not_used)
-{
-    struct sockaddr_in from;
-    socklen_t from_len;
-    LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
-    LOCAL_ARRAY(char, deb_line, 4096);
-    int len;
-    snmp_request_t *snmp_rq;
 
-    debug(49, 5) ("snmpHandleUdp: Called.\n");
-    commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
-    from_len = sizeof(struct sockaddr_in);
-    memset(&from, '\0', from_len);
-    Counter.syscalls.sock.recvfroms++;
-    len = recvfrom(sock,
-       buf,
-       SNMP_REQUEST_SIZE,
-       0,
-       (struct sockaddr *) &from,
-       &from_len);
-    if (len < 0) {
-#ifdef _SQUID_LINUX_
-       /* Some Linux systems seem to set the FD for reading and then
-        * return ECONNREFUSED when sendto() fails and generates an ICMP
-        * port unreachable message. */
-       /* or maybe an EHOSTUNREACH "No route to host" message */
-       if (errno != ECONNREFUSED && errno != EHOSTUNREACH)
-#endif
-           debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n",
-               sock, xstrerror());
-       return;
-    }
-    if (snmp_dump_packet) {
-       int count;
-       debug(49, 6) ("received %d bytes from %s:\n", (int) len,
-           inet_ntoa(from.sin_addr));
-       for (count = 0; count < len; count++) {
-           snprintf(deb_line, 4096, "%s %02X ", deb_line, (u_char) buf[count]);
-           if ((count % 16) == 15 || count == (len - 1)) {
-               debug(49, 8) ("snmp in: %s\n", deb_line);
-               deb_line[0] = '\0';
-           }
-       }
-    }
-    buf[len] = '\0';
-    debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
-       sock,
-       len,
-       inet_ntoa(from.sin_addr));
-
-    snmp_rq = xcalloc(1, sizeof(snmp_request_t));
-    snmp_rq->buf = (u_char *) buf;
-    snmp_rq->len = len;
-    snmp_rq->sock = sock;
-    snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
-    memcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
-    snmpAgentParse(snmp_rq);
-}
-
-void
-snmpAgentParseDone(int errstat, void *data)
-{
-    snmp_request_t *snmp_rq = (snmp_request_t *) data;
-    LOCAL_ARRAY(char, deb_line, 4096);
-    int sock = snmp_rq->sock;
-    long this_reqid = snmp_rq->reqid;
-    debug(49, 2) ("snmpAgentParseDone: errstat=%d, reqid=%d _t=%x\n",
-       errstat, this_reqid, snmp_rq);
-
-    if (memcmp(&snmp_rq->from, &local_snmpd, sizeof(struct sockaddr_in)) == 0) {
-       /* look it up */
-       if (snmpFwd_removePending(&snmp_rq->from, this_reqid)) {        /* failed */
-           debug(49, 2) ("snmp: bogus response from %s.\n",
-               inet_ntoa(snmp_rq->from.sin_addr));
-           if (snmp_rq->community)
-               xfree(snmp_rq->community);
-           xfree(snmp_rq->outbuf);
-           xfree(snmp_rq);
-           return;
-       }
-    }
-    switch (errstat) {
-    case 2:                    /* we might have to forward */
-       if (Config.Snmp.localPort != 0) {
-           snmpFwd_insertPending(&snmp_rq->from, this_reqid);
-           snmpUdpSend(sock, &local_snmpd, snmp_rq->outbuf, snmp_rq->outlen);
-           break;
-       }
-       debug(49, 4) ("snmp: can't forward.\n");
-       break;
-    case 1:                    /* everything is ok */
-       debug(49, 5) ("snmp: parsed.\n");
-       if (snmp_dump_packet) {
-           int count = 0;
-           debug(49, 5) ("snmp: sent %d bytes to %s\n", (int) snmp_rq->outlen,
-               inet_ntoa(snmp_rq->from.sin_addr));
-           for (count = 0; count < snmp_rq->outlen; count++) {
-               snprintf(deb_line, 4096, "%s %02X ", deb_line,
-                   (u_char) snmp_rq->outbuf[count]);
-               if ((count % 16) == 15 || count == (snmp_rq->len - 1)) {
-                   debug(49, 7) ("snmp out: %s\n", deb_line);
-                   deb_line[0] = '\0';
-               }
-           }
-       }
-       snmpUdpSend(snmp_rq->sock, &snmp_rq->from, snmp_rq->outbuf, snmp_rq->outlen);
-       break;
-    case 0:
-       debug(49, 5) ("snmpagentparsedone failed\n");
-       if (snmp_rq->outbuf)
-           xfree(snmp_rq->outbuf);
-       break;
-    }
-    if (snmp_rq->community)
-       xfree(snmp_rq->community);
-    cbdataFree(snmp_rq);
-    return;
-}
+/*
+ * The functions used during startup:
+ * snmpInit
+ * snmpConnectionOpen
+ * snmpConnectionShutdown
+ * snmpConnectionClose
+ */
 
+/*
+       Turns the MIB into a Tree structure. Called during the startup process.
+*/
 void
 snmpInit(void)
 {
-    assert(NULL != Config.Snmp.mibPath);
-    if (!snmpInitConfig())
-       debug(49, 0) ("snmpInit: snmpInitConfig() failed.\n");
+    debug(49, 5) ("snmpInit: Called.\n");
+
+    debug(49, 5) ("snmpInit: Building SNMP mib tree structure\n");
+
     snmplib_debug_hook = snmpSnmplibDebug;
 
-}
-int
-snmpInitConfig()
-{
-    wordlist *w;
-    char *buf;
-    char *tokens[10];
-
-    if (snmp_init_config)
-       return 1;
-
-    snmp_init_config = 1;
-    assert(NULL != Config.Snmp.mibPath);
-    if (Mib == NULL) {
-       debug(49, 3) ("init_mib: calling with %s\n", Config.Snmp.mibPath);
-       init_mib(Config.Snmp.mibPath);
-    }
-    if (Mib == NULL) {
-       debug(49, 0) ("WARNING: Failed to open MIB '%s'\n",
-           Config.Snmp.mibPath);
-       return 0;
-    }
-    /*
-     * Process 'snmp_agent_conf' lines
-     */
-    for (w = Config.Snmp.snmpconf; w != NULL; w = w->next) {
-       buf = xstrdup(w->key);
-       snmpTokenize(buf, tokens, 10);
-       if (0 == strcmp("view", tokens[0])) {
-           if (snmpCreateView(tokens) < 0) {
-               debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-               safe_free(buf);
-               return 0;
-           }
-       } else if (0 == strcmp("user", tokens[0])) {
-           if (snmpCreateUser(tokens) < 0) {
-               debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-               safe_free(buf);
-               return 0;
-           }
-       } else if (0 == strcmp("community", tokens[0])) {
-           if (snmpCreateCommunity(tokens) < 0)
-               debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-       } else {
-           debug(49, 1) ("snmpInit: error parsing '%s'\n", w->key);
-           safe_free(buf);
-           return 0;
-       }
-       safe_free(buf);
-    }
-    if (!Config.Snmp.communities) {
-       debug(49, 2) ("snmpInit: WARNING: communities not defined.\n");
-    } else
-       debug(49, 5) ("snmpInit: communities defined.\n");
-    snmpInitAgentAuth();
-    assert(0 <= snmpDefaultAuth());
-    return 1;
+    mib_tree_head = snmpAddNode(snmpCreateOid(1, 1),
+       1, NULL, 1,
+       snmpAddNode(snmpCreateOid(2, 1, 3),
+           2, NULL, 1,
+           snmpAddNode(snmpCreateOid(3, 1, 3, 6),
+               3, NULL, 1,
+               snmpAddNode(snmpCreateOid(4, 1, 3, 6, 1),
+                   4, NULL, 1,
+                   snmpAddNode(snmpCreateOid(5, 1, 3, 6, 1, 4),
+                       5, NULL, 1,
+                       snmpAddNode(snmpCreateOid(6, 1, 3, 6, 1, 4, 1),
+                           6, NULL, 1,
+                           snmpAddNode(snmpCreateOid(7, 1, 3, 6, 1, 4, 1, 3495),
+                               7, NULL, 1,
+                               snmpAddNode(snmpCreateOid(LEN_SQUIDMIB, SQUIDMIB),
+                                   8, NULL, 5,
+                                   snmpAddNode(snmpCreateOid(LEN_SQ_SYS, SQ_SYS),
+                                       LEN_SQ_SYS, NULL, 3,
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_SYS + 1, SQ_SYS, 1),
+                                           LEN_SQ_SYS + 1, snmp_sysFn, 0),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_SYS + 1, SQ_SYS, 2),
+                                           LEN_SQ_SYS + 1, snmp_sysFn, 0),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_SYS + 1, SQ_SYS, 3),
+                                           LEN_SQ_SYS + 1, snmp_sysFn, 0)),
+                                   snmpAddNode(snmpCreateOid(LEN_SQ_CONF, SQ_CONF),
+                                       LEN_SQ_CONF, NULL, 5,
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 1),
+                                           LEN_SQ_CONF + 1, snmp_confFn, 0),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 2),
+                                           LEN_SQ_CONF + 1, snmp_confFn, 0),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 3),
+                                           LEN_SQ_CONF + 1, snmp_confFn, 0),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 4),
+                                           LEN_SQ_CONF + 1, snmp_confFn, 0),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 1, SQ_CONF, 5),
+                                           LEN_SQ_CONF + 1, NULL, 6,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 1),
+                                               LEN_SQ_CONF + 2, snmp_confFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 2),
+                                               LEN_SQ_CONF + 2, snmp_confFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 3),
+                                               LEN_SQ_CONF + 2, snmp_confFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 4),
+                                               LEN_SQ_CONF + 2, snmp_confFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 5),
+                                               LEN_SQ_CONF + 2, snmp_confFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_CONF + 2, SQ_CONF, 5, 6),
+                                               LEN_SQ_CONF + 2, snmp_confFn, 0))),
+                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF, SQ_PRF),
+                                       LEN_SQ_PRF, snmp_confFn, 2,
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, 1),
+                                           LEN_SQ_PRF + 1, snmp_sysFn, 11,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 1),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 2),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 3),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 4),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 5),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 6),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 7),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 8),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 9),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 10),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 1, 11),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 0)),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 1, SQ_PRF, 2),
+                                           LEN_SQ_PRF + 1, snmp_sysFn, 2,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 2, 1),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 14,
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 1),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 2),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 3),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 4),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 5),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 6),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 7),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 8),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 9),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 10),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 11),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 12),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 13),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 1, 14),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 0)),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 2, SQ_PRF, 2, 2),
+                                               LEN_SQ_PRF + 2, snmp_sysFn, 1,
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 3, SQ_PRF, 2, 2, 1),
+                                                   LEN_SQ_PRF + 3, snmp_sysFn, 8,
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 1),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0),
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 2),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0),
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 3),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0),
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 4),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0),
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 5),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0),
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 6),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0),
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 7),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0),
+                                                   snmpAddNode(snmpCreateOid(LEN_SQ_PRF + 4, SQ_PRF, 2, 2, 1, 8),
+                                                       LEN_SQ_PRF + 4, snmp_sysFn, 0))))),
+                                   snmpAddNode(snmpCreateOid(LEN_SQ_NET, SQ_NET),
+                                       LEN_SQ_NET, snmp_confFn, 3,
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, 1),
+                                           LEN_SQ_NET + 1, snmp_sysFn, 9,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 1),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 2),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 3),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 4),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 5),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 6),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 7),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 8),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 1, 9),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0)),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, 2),
+                                           LEN_SQ_NET + 1, snmp_sysFn, 8,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 1),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 2),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 3),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 4),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 5),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 6),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 7),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 2, 8),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0)),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_NET + 1, SQ_NET, 3),
+                                           LEN_SQ_NET + 1, snmp_sysFn, 3,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 3, 1),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 3, 2),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0),
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_NET + 2, SQ_NET, 3, 3),
+                                               LEN_SQ_NET + 2, snmp_sysFn, 0))),
+                                   snmpAddNode(snmpCreateOid(LEN_SQ_MESH, SQ_MESH),
+                                       LEN_SQ_MESH, snmp_confFn, 2,
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 1),
+                                           LEN_SQ_MESH + 1, snmp_sysFn, 1,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 1, 1),
+                                               LEN_SQ_MESH + 2, snmp_sysFn, 13,
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 1),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 2),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 3),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 4),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 5),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 6),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 7),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 8),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 9),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 10),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 11),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 12),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 1, 1, 13),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0))),
+                                       snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 1, SQ_MESH, 2),
+                                           LEN_SQ_MESH + 1, snmp_sysFn, 1,
+                                           snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 2, SQ_MESH, 2, 1),
+                                               LEN_SQ_MESH + 2, snmp_sysFn, 9,
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 1),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 2),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 3),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 4),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 5),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 6),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 7),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 8),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0),
+                                               snmpAddNode(snmpCreateOid(LEN_SQ_MESH + 3, SQ_MESH, 2, 1, 9),
+                                                   LEN_SQ_MESH + 3, snmp_sysFn, 0))))
+                               )
+                           )
+                       )
+                   )
+               )
+           )
+       )
+       );
+
+    debug(49, 9) ("snmpInit: Completed SNMP mib tree structure\n");
 }
 
 void
 snmpConnectionOpen(void)
 {
     u_short port;
-    struct in_addr addr;
     struct sockaddr_in xaddr;
     socklen_t len;
     int x;
 
+       debug(49, 5) ("snmpConnectionOpen: Called\n");
     if ((port = Config.Port.snmp) > (u_short) 0) {
-       enter_suid();
-       theInSnmpConnection = comm_open(SOCK_DGRAM,
-           0,
-           Config.Addrs.snmp_incoming,
-           port,
-           COMM_NONBLOCKING,
-           "SNMP Port");
-       leave_suid();
-       if (theInSnmpConnection < 0)
-           fatal("Cannot open snmp Port");
-       commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
-       debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
-           (int) port, theInSnmpConnection);
-       if ((addr = Config.Addrs.snmp_outgoing).s_addr != no_addr.s_addr) {
-           enter_suid();
-           theOutSnmpConnection = comm_open(SOCK_DGRAM,
-               0,
-               addr,
-               port,
-               COMM_NONBLOCKING,
-               "SNMP Port");
-           leave_suid();
-           if (theOutSnmpConnection < 0)
-               fatal("Cannot open Outgoing SNMP Port");
-           commSetSelect(theOutSnmpConnection,
-               COMM_SELECT_READ,
-               snmpHandleUdp,
-               NULL, 0);
-           debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n",
-               (int) port, theOutSnmpConnection);
-           fd_note(theOutSnmpConnection, "Outgoing SNMP socket");
-           fd_note(theInSnmpConnection, "Incoming SNMP socket");
-       } else {
-           theOutSnmpConnection = theInSnmpConnection;
-       }
-       memset(&theOutSNMPAddr, '\0', sizeof(struct in_addr));
-       len = sizeof(struct sockaddr_in);
-       memset(&xaddr, '\0', len);
-       x = getsockname(theOutSnmpConnection,
-           (struct sockaddr *) &xaddr, &len);
-       if (x < 0)
-           debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
-               theOutSnmpConnection, xstrerror());
-       else {
-           theOutSNMPAddr = xaddr.sin_addr;
-           if (Config.Snmp.localPort != 0) {
-               local_snmpd.sin_addr = xaddr.sin_addr;
-               local_snmpd.sin_port = Config.Snmp.localPort;
-           }
-       }
+        enter_suid();
+        theInSnmpConnection = comm_open(SOCK_DGRAM,
+            0,
+            Config.Addrs.snmp_incoming,
+            port,
+            COMM_NONBLOCKING,
+            "SNMP Port");
+        leave_suid();
+        if (theInSnmpConnection < 0)
+            fatal("Cannot open snmp Port");
+        commSetSelect(theInSnmpConnection, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
+        debug(1, 1) ("Accepting SNMP messages on port %d, FD %d.\n",
+            (int) port, theInSnmpConnection);
+        if (Config.Addrs.snmp_outgoing.s_addr != no_addr.s_addr) {
+            enter_suid();
+            theOutSnmpConnection = comm_open(SOCK_DGRAM,
+                0,
+                Config.Addrs.snmp_outgoing,
+                port,
+                COMM_NONBLOCKING,
+                "SNMP Port");
+            leave_suid();
+            if (theOutSnmpConnection < 0)
+                fatal("Cannot open Outgoing SNMP Port");
+            commSetSelect(theOutSnmpConnection,
+                COMM_SELECT_READ,
+                snmpHandleUdp,
+                NULL, 0);
+            debug(1, 1) ("Outgoing SNMP messages on port %d, FD %d.\n",
+                (int) port, theOutSnmpConnection);
+            fd_note(theOutSnmpConnection, "Outgoing SNMP socket");
+            fd_note(theInSnmpConnection, "Incoming SNMP socket");
+        } else {
+            theOutSnmpConnection = theInSnmpConnection;
+        }
+        memset(&theOutSNMPAddr, '\0', sizeof(struct in_addr));
+        len = sizeof(struct sockaddr_in);
+        memset(&xaddr, '\0', len);
+        x = getsockname(theOutSnmpConnection,
+            (struct sockaddr *) &xaddr, &len);
+        if (x < 0)
+            debug(51, 1) ("theOutSnmpConnection FD %d: getsockname: %s\n",
+                theOutSnmpConnection, xstrerror());
+        else 
+            theOutSNMPAddr = xaddr.sin_addr;
     }
 }
 
-void
-snmpFwd_insertPending(struct sockaddr_in *ad, long reqid)
-{
-    struct snmpFwdQueue *new;
-
-    new = (struct snmpFwdQueue *) xcalloc(1, sizeof(struct snmpFwdQueue));
-    xmemcpy(&new->addr, ad, sizeof(struct sockaddr_in));
-    new->req_id = reqid;
-    new->req_time = squid_curtime;
-    if (snmpHead == NULL) {
-       new->next = NULL;
-       snmpHead = new;
-    }
-    new->next = snmpHead;
-    snmpHead = new;
-}
-
-int
-snmpFwd_removePending(struct sockaddr_in *fr, long reqid)
-{
-    struct snmpFwdQueue *p, *prev = NULL;
-    for (p = snmpHead; p != NULL; p = p->next, prev = p)
-       if (reqid == p->req_id) {
-           xmemcpy(fr, &p->addr, sizeof(struct sockaddr_in));
-           if (p == snmpHead)
-               snmpHead = p->next;
-           else if (p->next == NULL)
-               prev->next = NULL;
-           debug(49, 3) ("snmpFwd_removePending: freeing %p\n", p);
-           xfree(p);
-           return 0;
-       }
-    return 1;
-}
-
-void
-snmpUdpSend(int fd,
-    const struct sockaddr_in *to,
-    void *msg, int len)
-{
-    snmpUdpData *data = xcalloc(1, sizeof(snmpUdpData));
-    debug(49, 5) ("snmpUdpSend: Queueing response for %s\n",
-       inet_ntoa(to->sin_addr));
-    data->address = *to;
-    data->msg = msg;
-    data->len = len;
-    snmpAppendUdp(data);
-    commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
-
-}
-void
-snmpUdpReply(int fd, void *data)
-{
-    snmpUdpData *queue = data;
-    int x;
-    /* Disable handler, in case of errors. */
-    commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
-    while ((queue = snmpUdpHead) != NULL) {
-       debug(49, 5) ("snmpUdpReply: FD %d sending %d bytes to %s port %d\n",
-           fd,
-           queue->len,
-           inet_ntoa(queue->address.sin_addr),
-           ntohs(queue->address.sin_port));
-       x = comm_udp_sendto(fd,
-           &queue->address,
-           sizeof(struct sockaddr_in),
-           queue->msg,
-           queue->len);
-       if (x < 0) {
-           if (ignoreErrno(errno))
-               break;          /* don't de-queue */
-       }
-       snmpUdpHead = queue->next;
-       debug(49, 3) ("snmpUdpReply: freeing %p\n", queue->msg);
-       safe_free(queue->msg);
-       debug(49, 3) ("snmpUdpReply: freeing %p\n", queue);
-       safe_free(queue);
-    }
-    /* Reinstate handler if needed */
-    if (snmpUdpHead) {
-       commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
-    }
-}
-
-void
-snmpAppendUdp(snmpUdpData * item)
-{
-    item->next = NULL;
-    if (snmpUdpHead == NULL) {
-       snmpUdpHead = item;
-       snmpUdpTail = item;
-    } else if (snmpUdpTail == snmpUdpHead) {
-       snmpUdpTail = item;
-       snmpUdpHead->next = item;
-    } else {
-       snmpUdpTail->next = item;
-       snmpUdpTail = item;
-    }
-
-}
-
 void
 snmpConnectionShutdown(void)
 {
     if (theInSnmpConnection < 0)
-       return;
+        return;
     if (theInSnmpConnection != theOutSnmpConnection) {
-       debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection);
-       comm_close(theInSnmpConnection);
+        debug(49, 1) ("FD %d Closing SNMP socket\n", theInSnmpConnection);
+        comm_close(theInSnmpConnection);
     }
     /*
      * Here we set 'theInSnmpConnection' to -1 even though the SNMP 'in'
@@ -484,7 +413,7 @@ snmpConnectionShutdown(void)
      * function from executing repeatedly.  When we are really ready to
      * exit or restart, main will comm_close the 'out' descriptor.
      */ theInSnmpConnection = -1;
-    /* 
+    /*
      * Normally we only write to the outgoing SNMP socket, but we
      * also have a read handler there to catch messages sent to that
      * specific interface.  During shutdown, we must disable reading
@@ -499,351 +428,421 @@ snmpConnectionClose(void)
 {
     snmpConnectionShutdown();
     if (theOutSnmpConnection > -1) {
-       debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection);
-       comm_close(theOutSnmpConnection);
+        debug(49, 1) ("FD %d Closing SNMP socket\n", theOutSnmpConnection);
+        comm_close(theOutSnmpConnection);
     }
 }
 
-/* returns: 
- * 2: no such object in this mib
- * 1: ok
- * 0: failed */
+/*
+       Functions for handling the requests.
+*/
 
+/*
+ * Accept the UDP packet
+ */
 void
-snmpAgentParse(void *data)
+snmpHandleUdp(int sock, void *not_used)
 {
-    snmp_request_t *rq = (snmp_request_t *) data;
-    u_char *buf = rq->buf;
-    int len = rq->len;
+    LOCAL_ARRAY(char, buf, SNMP_REQUEST_SIZE);
+    struct sockaddr_in from;
+    socklen_t from_len;
+    snmp_request_t *snmp_rq;
+    int len;
+
+    debug(49, 5) ("snmpHandleUdp: Called.\n");
+
+    commSetSelect(sock, COMM_SELECT_READ, snmpHandleUdp, NULL, 0);
+    from_len = sizeof(struct sockaddr_in);
+    memset(&from, '\0', from_len);
+
+    Counter.syscalls.sock.recvfroms++;
+
+    len = recvfrom(sock,
+       buf,
+       SNMP_REQUEST_SIZE,
+       0,
+       (struct sockaddr *) &from,
+       &from_len);
+
+    if (len > 0) {
+       buf[len] = '\0';
+       debug(49, 3) ("snmpHandleUdp: FD %d: received %d bytes from %s.\n",
+           sock,
+           len,
+           inet_ntoa(from.sin_addr));
+
+       snmp_rq = xcalloc(1, sizeof(snmp_request_t));
+       snmp_rq->buf = (u_char *) buf;
+       snmp_rq->len = len;
+       snmp_rq->sock = sock;
+       snmp_rq->outbuf = xmalloc(snmp_rq->outlen = SNMP_REQUEST_SIZE);
+       memcpy(&snmp_rq->from, &from, sizeof(struct sockaddr_in));
+       snmpDecodePacket(snmp_rq);
+    } else {
+       debug(49, 1) ("snmpHandleUdp: FD %d recvfrom: %s\n", sock, xstrerror());
+    }
+}
 
+/*
+ * Turn SNMP packet into a PDU, check available ACL's
+ */
+void
+snmpDecodePacket(snmp_request_t * rq)
+{
     struct snmp_pdu *PDU;
+    struct snmp_session *Session;
+    aclCheck_t checklist;
     u_char *Community;
+    u_char *buf = rq->buf;
+    int len = rq->len;
+    int allow = 0;
 
+    debug(49, 5) ("snmpDecodePacket: Called.\n");
     /* Now that we have the data, turn it into a PDU */
+    Session = (struct snmp_session *) xmalloc(sizeof(struct snmp_session));
+    Session->Version = SNMP_VERSION_1;
+    Session->authenticator = NULL;
+    Session->community = (u_char *) xstrdup("public");
+    Session->community_len = 6;
     cbdataAdd(rq, MEM_NONE);
     PDU = snmp_pdu_create(0);
     Community = snmp_parse(Session, PDU, buf, len);
 
-    if (!snmp_coexist_V2toV1(PDU)) {   /* incompatibility */
-       debug(49, 3) ("snmpAgentParse: Incompatible V2 packet.\n");
+    checklist.src_addr = rq->from.sin_addr;
+    checklist.snmp_community = Community;
+
+    allow = aclCheckFast(Config.accessList.snmp, &checklist);
+    if ((snmp_coexist_V2toV1(PDU)) && (Community) && (allow)) {
+       rq->community = Community;
+       rq->PDU = PDU;
+       debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
+       snmpConstructReponse(rq, Session);
+    } else {
        snmp_free_pdu(PDU);
-       snmpAgentParseDone(0, rq);
-       return;
     }
-    rq->community = Community;
-    rq->PDU = PDU;
-    debug(49, 5) ("snmpAgentParse: reqid=[%d]\n", PDU->reqid);
+}
 
-    if (!Community) {
-       debug(49, 2) ("snmpAgentParse: WARNING: Could not parse community\n");
+/*
+ * Packet OK, ACL Check OK, Create reponse.
+ */
+void
+snmpConstructReponse(snmp_request_t * rq, struct snmp_session *Session)
+{
+    struct snmp_pdu *RespPDU;
+    int ret;
 
-       snmp_free_pdu(PDU);
-       snmpAgentParseDone(0, rq);
-       return;
+    debug(49, 5) ("snmpConstructReponse: Called.\n");
+
+    Session->community = rq->community;
+    Session->community_len = strlen((char *) rq->community);
+
+    RespPDU = snmpAgentResponse(rq->PDU);
+    snmp_free_pdu(rq->PDU);
+    xfree(Session);
+    if (RespPDU == NULL) {
+    } else {
+       ret = snmp_build(Session, RespPDU, rq->outbuf, &rq->outlen);
+       snmpUdpSend(rq->sock, &rq->from, rq->outbuf, rq->outlen);
+       snmp_free_pdu(RespPDU);
     }
-    snmpAclCheckStart(rq);
 }
 
+/*
+ * Decide how to respond to the request, construct a response and
+ * return the response to the requester.
+ * 
+ * If configured forward any reponses which are not for this agent.
+ */
 struct snmp_pdu *
 snmpAgentResponse(struct snmp_pdu *PDU)
 {
     struct snmp_pdu *Answer = NULL;
-    variable_list *VarPtr, *VarNew = NULL;
-    variable_list **VarPtrP, **RespVars;
-    int index = 0;
-    oid_ParseFn *ParseFn;
-
-    debug(49, 9) ("snmpAgentResponse: Received a %d PDU\n", PDU->command);
+    oid_ParseFn *ParseFn = NULL;
+    variable_list *VarNew = NULL;
 
-    /* Create a response */
-    Answer = snmp_pdu_create(SNMP_PDU_RESPONSE);
-    if (Answer == NULL)
-       return (NULL);
-    Answer->reqid = PDU->reqid;
-    Answer->errindex = 0;
+    debug(49, 5) ("snmpAgentResponse: Called.\n");
 
-    if (PDU->command == SNMP_PDU_GET) {
+    if ((Answer = snmp_pdu_create(SNMP_PDU_RESPONSE))) {
+       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;
+       } else if (PDU->command == SNMP_PDU_GETNEXT) {
+           oid *NextOidName = NULL;
+           int NextOidNameLen = 0;
 
-           index++;
-
-           /* Find the parsing function for this variable */
-           ParseFn = oidlist_Find(VarPtr->name, VarPtr->name_length);
+           ParseFn = snmpTreeNext(PDU->variables->name, PDU->variables->name_length,
+               &(NextOidName), (snint *) &NextOidNameLen);
 
            if (ParseFn == NULL) {
                Answer->errstat = SNMP_ERR_NOSUCHNAME;
-               debug(49, 5) ("snmpAgentResponse: No such oid. ");
-           } else
-               VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
+               debug(49, 5) ("snmpAgentResponse: No such oid: ");
+               snmpDebugOid(5, PDU->variables->name, PDU->variables->name_length);
+           } else {
+               xfree(PDU->variables->name);
+               PDU->variables->name = NextOidName;
+               PDU->variables->name_length = NextOidNameLen;
+               VarNew = (*ParseFn) (PDU->variables, (snint *) &Answer->errstat);
+           }
 
            /* Was there an error? */
-           if ((Answer->errstat != SNMP_ERR_NOERROR) ||
-               (VarNew == NULL)) {
-               Answer->errindex = index;
-               debug(49, 5) ("snmpAgentParse: successful.\n");
-               /* Just copy the rest of the variables.  Quickly. */
-               *RespVars = VarPtr;
-               *VarPtrP = NULL;
-               return (Answer);
+           if (Answer->errstat != SNMP_ERR_NOERROR) {
+               Answer->errindex = 1;
+
+               /* Just copy this variable */
+               Answer->variables = PDU->variables;
+               PDU->variables = NULL;
+           } else {
+               Answer->variables = VarNew;
            }
-           /* 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), (snint *) & (TmpOidNameLen));
-
-       if (ParseFn == NULL) {
-           Answer->errstat = SNMP_ERR_NOSUCHNAME;
-           debug(49, 5) ("snmpAgentResponse: No such oid: ");
-           snmpDebugOid(5, VarPtr->name, VarPtr->name_length);
-       } else {
-           xfree(VarPtr->name);
-           VarPtr->name = TmpOidName;
-           VarPtr->name_length = TmpOidNameLen;
-           VarNew = (*ParseFn) (VarPtr, (snint *) & (Answer->errstat));
+
+       }else{
+               snmp_free_pdu(Answer);
+               Answer = NULL;
        }
+    }
+    return (Answer);
+}
 
-       /* Was there an error? */
-       if (Answer->errstat != SNMP_ERR_NOERROR) {
-           Answer->errindex = 1;
+oid_ParseFn *
+snmpTreeNext(oid * Current, snint CurrentLen, oid ** Next, snint * NextLen)
+{
+    oid_ParseFn *Fn = NULL;
+    mib_tree_entry *mibTreeEntry = NULL, *new_oid = NULL;
+    int count = 0;
+
+    debug(49, 5) ("snmpTreeNext: Called\n");
+
+    debug(49, 6) ("snmpTreeNext: Current : \n");
+    snmpDebugOid(6, Current, CurrentLen);
 
-           /* Just copy this variable */
-           Answer->variables = VarPtr;
-           PDU->variables = NULL;
-       } else {
-           Answer->variables = VarNew;
+    mibTreeEntry = mib_tree_head;
+    if (Current[count] == mibTreeEntry->name[count]) {
+       count++;
+       while ((mibTreeEntry) && (count < CurrentLen)) {
+           mibTreeEntry = snmpTreeEntry(Current[count], count , mibTreeEntry);
+           count++;
        }
+       debug(49, 5) ("snmpTreeNext: Past first\n");
+
+       if (mibTreeEntry->parsefunction) {
+           while(!new_oid){
+               new_oid = snmpTreeEntry(Current[count]+1, count , mibTreeEntry->parent);
+               if(!new_oid){
+                   mibTreeEntry = mibTreeEntry->parent;
+                   count--;
+               }
+           }
+       } 
+       debug(49, 5) ("snmpTreeNext: Past Second\n");
 
-       /* Done.  Return this PDU */
-       return (Answer);
-    }                          /* end SNMP_PDU_GETNEXT */
-    debug(49, 5) ("snmpAgentResponse: Ignoring PDU %d unknown command\n", PDU->command);
-    snmp_free_pdu(Answer);
-    return (NULL);
+       if ((!mibTreeEntry->parsefunction) && (mibTreeEntry)) {
+           while (!mibTreeEntry->parsefunction) {
+               mibTreeEntry = snmpTreeEntry(1, count , mibTreeEntry);
+               count++;
+           }
+       }
+       debug(49, 5) ("snmpTreeNext: Past Third\n");
+    }
+    if(mibTreeEntry){
+        *Next = snmpOidDup(mibTreeEntry->name, mibTreeEntry->len);
+        *NextLen = mibTreeEntry->len;
+       Fn = mibTreeEntry->parsefunction;
+    }
+    debug(49, 5) ("snmpTreeNext: return\n");
+    return (Fn);
 }
 
-void
-snmpDebugOid(int lvl, oid * Name, snint Len)
+mib_tree_entry *
+snmpTreeEntry(oid entry, snint len, mib_tree_entry * current)
 {
-    char mbuf[16], objid[1024];
-    int x;
-    objid[0] = '\0';
+    mib_tree_entry *next = NULL;
+    int count = 0;
 
-    for (x = 0; x < Len; x++) {
-       snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
-       strncat(objid, mbuf, sizeof(objid));
-    }
+    debug(49, 5) ("snmpTreeEntry: Called\n");
 
-    debug(49, lvl) ("   oid = %s\n", objid);
-}
+    debug(49, 6) ("snmpTreeEntry: Oid: %d, Len: %d, Current : \n",entry, len);
+    snmpDebugOid(6, current->name, current->len);
 
-int
-oidcmp(oid * A, snint ALen, oid * B, snint BLen)
-{
-    oid *aptr = A;
-    oid *bptr = B;
-    snint m = MIN(ALen, BLen);
-
-    /* Compare the first M bytes. */
-    while (m) {
-       if (*aptr < *bptr)
-           return (-1);
-       if (*aptr++ > *bptr++)
-           return (1);
-       m--;
+    while ((!next) && (count < current->children)) {
+       debug(49, 6) ("snmpTreeEntry: While loop count: %d, children: %d \n", count, current->children);
+       snmpDebugOid(6, current->leaves[count]->name, current->leaves[count]->len);
+       if (current->leaves[count]->name[len] == entry) {
+           next = current->leaves[count];
+       }
+       count++;
     }
+    if(next){
+       debug(49, 6) ("snmpTreeEntry: Returned : \n");
+       snmpDebugOid(6, next->name, next->len);
+    }
+    return (next);
+}
 
-    /* The first M bytes were identical.  So, they share the same
-     * root.  The shorter one must come first.
-     */
-    if (ALen < BLen)
-       return (-1);
+/*
+       Send the UDP reply.
+*/
+void
+snmpUdpSend(int fd, const struct sockaddr_in *to, void *msg, int len)
+{
+    snmpUdpData *data = xcalloc(1, sizeof(snmpUdpData));
+    debug(49, 5) ("snmpUdpSend: Queueing response for %s\n",
+        inet_ntoa(to->sin_addr));
+    data->address = *to;
+    data->msg = msg;
+    data->len = len;
+    snmpAppendUdp(data);
+    commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
 
-    if (ALen > BLen)
-       return (1);
+}
 
-    /* Same length, all bytes identical.  Must be the same OID. */
-    return (0);
+void
+snmpUdpReply(int fd, void *data)
+{
+    snmpUdpData *queue = data;
+    int x;
+    /* Disable handler, in case of errors. */
+    commSetSelect(fd, COMM_SELECT_WRITE, NULL, NULL, 0);
+    while ((queue = snmpUdpHead) != NULL) {
+        debug(49, 5) ("snmpUdpReply: FD %d sending %d bytes to %s port %d\n",
+            fd,
+            queue->len,
+            inet_ntoa(queue->address.sin_addr),
+            ntohs(queue->address.sin_port));
+        x = comm_udp_sendto(fd,
+            &queue->address,
+            sizeof(struct sockaddr_in),
+            queue->msg,
+            queue->len);
+        if (x < 0) {
+            if (ignoreErrno(errno))
+                break;          /* don't de-queue */
+        }
+        snmpUdpHead = queue->next;
+        debug(49, 3) ("snmpUdpReply: freeing %p\n", queue->msg);
+        safe_free(queue->msg);
+        debug(49, 3) ("snmpUdpReply: freeing %p\n", queue);
+        safe_free(queue);
+    }
+    /* Reinstate handler if needed */
+    if (snmpUdpHead) {
+        commSetSelect(fd, COMM_SELECT_WRITE, snmpUdpReply, snmpUdpHead, 0);
+    }
 }
 
-int
-oidncmp(oid * A, snint ALen, oid * B, snint BLen, snint CompLen)
+void
+snmpAppendUdp(snmpUdpData * item)
 {
-    oid *aptr = A;
-    oid *bptr = B;
-    snint m = MIN(MIN(ALen, BLen), CompLen);
-    snint count = 0;
-
-    /* Compare the first M bytes. */
-    while (count != m) {
-       if (*aptr < *bptr)
-           return (-1);
-       if (*aptr++ > *bptr++)
-           return (1);
-       count++;
+    item->next = NULL;
+    if (snmpUdpHead == NULL) {
+        snmpUdpHead = item;
+        snmpUdpTail = item;
+    } else if (snmpUdpTail == snmpUdpHead) {
+        snmpUdpTail = item;
+        snmpUdpHead->next = item;
+    } else {
+        snmpUdpTail->next = item;
+        snmpUdpTail = item;
     }
 
-    if (m == CompLen)
-       return (0);
+}
 
+/*
+        Utility functions
+*/
 
-    if (ALen < BLen)
-       return (-1);
+/*
+        Tree utility functions. 
+*/
 
-    if (ALen > BLen)
-       return (1);
+/*
+        Adds a node to the MIB tree structure and adds the appropriate children
+*/
+mib_tree_entry*
+snmpAddNode(oid *name, int len, oid_ParseFn *parsefunction, int children,  ...)
+{
+        va_list args;
+        int loop;
+        mib_tree_entry *entry = NULL;
+
+        debug(49, 6) ("snmpAddNode: Children : %d, Oid : \n", children);
+        snmpDebugOid(6, name, len);
+
+        va_start(args, children);
+        entry = xmalloc(sizeof(mib_tree_entry));
+        entry->name = snmpOidDup(name, len);
+        entry->len = len;
+        entry->parsefunction = parsefunction;
+        entry->children = children;
+
+        if(children > 0){
+                entry->leaves = xmalloc(sizeof(mib_tree_entry*)*children);
+                for(loop = 0;loop < children;loop++){
+                        entry->leaves[loop] = va_arg(args, mib_tree_entry*);
+                       entry->leaves[loop]->parent = entry;
+                }
+        }
+        return(entry);
+}
+/* End of tree utility functions */
 
-    /* Same length, all bytes identical.  Must be the same OID. */
-    return (0);
+/* 
+        Returns the list of parameters in an oid[]
+*/
+oid*
+snmpCreateOid(int length, ...)
+{
+        va_list args;
+        oid     *new_oid;
+        int     loop;
+
+        va_start(args, length);
+        new_oid = xmalloc(sizeof(oid)*length);
+
+        if(length > 0){
+                for(loop = 0;loop < length;loop++){
+                        new_oid[loop] = va_arg(args, int);
+                }
+        }
+        return(new_oid);
 }
 
-/* Allocate space for, and copy, an OID.  Returns new oid, or NULL.
+/*
+        Allocate space for, and copy, an OID.  Returns new oid, or NULL.
  */
 oid *
-oiddup(oid * A, snint ALen)
+snmpOidDup(oid * A, snint ALen)
 {
     oid *Ans;
-
-    Ans = (oid *) xmalloc(sizeof(oid) * ALen);
+    Ans = (oid *) xmalloc(sizeof(oid) * ALen); 
     if (Ans)
-       memcpy(Ans, A, (sizeof(oid) * ALen));
+        memcpy(Ans, A, (sizeof(oid) * ALen));
     return (Ans);
 }
 
+/*
+        Debug calls, prints out the OID for debugging purposes.
+*/
+void
+snmpDebugOid(int lvl, oid * Name, snint Len)
+{   
+    char mbuf[16], objid[1024];
+    int x;
+    objid[0] = '\0';
 
-/**********************************************************************
- * OIDLIST FUNCTIONS
- *
- * Find the parsing function for OIDs registered in this agent.
- **********************************************************************/
-
-oid_ParseFn *
-oidlist_Find(oid * Src, snint SrcLen)
-{
-    struct MIBListEntry *Ptr;
-    int ret;
-
-    debug(49, 7) ("oidlist_Find:  Called.\n ");
-    snmpDebugOid(7, Src, SrcLen);
-
-    for (Ptr = squidMIBList; Ptr->GetFn; Ptr++) {
-
-       ret = oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen);
-
-       if (!ret) {
-
-           /* Cool.  We found the mib it's in.  Let it find the function.
-            */
-           debug(49, 7) ("oidlist_Find:  found, returning GetFn Ptr! \n");
-
-           return ((*Ptr->GetFn) (Src, SrcLen));
-       }
-       if (ret < 0) {
-           debug(49, 7) ("oidlist_Find:  We just passed it, so it doesn't exist.\n ");
-           /* We just passed it, so it doesn't exist. */
-           return (NULL);
-       }
+    for (x = 0; x < Len; x++) {
+        snprintf(mbuf, sizeof(mbuf), ".%u", (unsigned int) Name[x]);
+        strncat(objid, mbuf, sizeof(objid));
     }
-
-    debug(49, 5) ("oidlist_Find:  the request was past the end.  It doesn't exist.\n");
-    /* We get here if the request was past the end.  It doesn't exist. */
-    return (NULL);
+    
+    debug(49, lvl) ("   oid = %s\n", objid);
 }
-/* Find the next item.  For SNMP_PDU_GETNEXT requests. 
- *
- * Returns a pointer to the parser function, and copies the oid to dest.
- * 
- * This is just plain ugly and needs a total rewrite, these changes are
- * to make it work, nothing else!
- *
- */
-oid_ParseFn *
-oidlist_Next(oid * Src, snint SrcLen, oid ** DestP, snint * DestLenP)
-{
-    struct MIBListEntry *Ptr;
-    int ret;
-    oid_ParseFn *Fn = NULL;
-
-    debug(49, 7) ("oidlist_Next: Looking for next of:\n");
-    snmpDebugOid(7, Src, SrcLen);
-
-    for (Ptr = squidMIBList; Ptr->GetNextFn; Ptr++) {
-
-       /* Only look at as much as we have stored */
-       ret = oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen);
 
-       if (!ret) {
-           debug(49, 6) ("oidlist_Next: Checking MIB\n");
-
-           /* Cool.  We found the mib it's in.  Ask it.
-            */
-           while (Ptr != NULL && Ptr->GetNextFn) {
-               Fn = ((*Ptr->GetNextFn) (Src, SrcLen, DestP, DestLenP));
-               if (Fn == NULL) {
-                   /* If this returned NULL, we're looking for the first
-                    * in the next MIB.
-                    */
-                   debug(49, 6) ("oidlist_Next: Not in this entry. Trying next.\n");
-                   Ptr++;
-                   continue;
-               }
-               return Fn;
-           }
-           /* Return what we found.  NULL if it wasn't in the MIB, and there
-            * were no more MIBs. 
-            */
-           debug(49, 3) ("oidlist_Next: No next mib.\n");
-           return NULL;
-       }
-       if (ret < 0) {
-           /* We just passed the mib it would be in.  Return 
-            * the next in this MIB.
-            */
-           debug(49, 3) ("oidlist_Next: Passed mib.  Checking this one.\n");
-           while (Ptr != NULL && Ptr->GetNextFn) {
-               Fn = ((*Ptr->GetNextFn) (Src, SrcLen, DestP, DestLenP));
-               if (Fn == NULL && oidncmp(Src, SrcLen, Ptr->Name, Ptr->NameLen, Ptr->NameLen) < 0) {
-                   debug(49, 6) ("oidlist_Next: Not in this entry. Trying next.\n");
-                   Ptr++;
-                   continue;
-               } else {
-                   return Fn;
-               }
-           }
-           debug(49, 3) ("oidlist_Next: No next mib.\n");
-           return NULL;
-       }
-    }
+static void     
+snmpSnmplibDebug(int lvl, char *buf)
+{           
+    debug(49, lvl) ("%s", buf);
+}           
 
-    /* We get here if the request was past the end.  It doesn't exist. */
-    debug(49, 7) ("oidlist_Next: Found nothing.\n");
-    return (NULL);
-}
 
-struct in_addr *
-gen_getMax()
-{
-    static struct in_addr maddr;
-#if USE_ICMP
-    safe_inet_addr("255.255.255.255", &maddr);
-#else
-    safe_inet_addr("0.0.0.0", &maddr);
-#endif
-    return &maddr;
-}
index 2a302cf92487606a5261a8ce2f9a801a7d131dfb..6ace70f3b9fb8e7a577fffacd5ebfe9cff1e02db 100644 (file)
@@ -1,7 +1,7 @@
 
 
 /*
- * $Id: structs.h,v 1.245 1998/10/19 22:37:05 wessels Exp $
+ * $Id: structs.h,v 1.246 1998/11/11 20:04:20 glenn Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -109,36 +109,6 @@ struct _snmp_request_t {
     u_char *community;
 };
 
-struct _viewEntry {
-    char viewName[32];
-    int viewIndex;
-    int viewType;
-    int viewSubtreeLen;
-    oid viewSubtree[32];
-    struct _viewEntry *next;
-};
-
-struct _communityEntry {
-    char name[64];
-    int readView;
-    int writeView;
-    acl_access *acls;
-    communityEntry *next;
-};
-
-struct _usecEntry {
-    u_char userName[32];
-    int userLen;
-    int qoS;
-    u_char authKey[16];
-    u_char privKey[16];
-    int noauthReadView;
-    int noauthWriteView;
-    int authReadView;
-    int authWriteView;
-    usecEntry *next;
-};
-
 #endif
 
 struct _acl {
@@ -171,6 +141,9 @@ struct _aclCheck_t {
     char browser[BROWSERNAMELEN];
     acl_proxy_auth_user *auth_user;
     acl_lookup_state state[ACL_ENUM_MAX];
+#if SQUID_SNMP
+    char *snmp_community;
+#endif
     PF *callback;
     void *callback_data;
 };
@@ -261,16 +234,7 @@ struct _SquidConfig {
     struct {
        char *configFile;
        char *agentInfo;
-       char *mibPath;
-       char *trap_community;
-       char *trap_sink;
        u_short localPort;
-       int do_queueing;
-       int conf_authtraps;
-       wordlist *snmpconf;
-       viewEntry *views;
-       usecEntry *users;
-       communityEntry *communities;
     } Snmp;
 #endif
     char *as_whois_server;
@@ -387,6 +351,9 @@ struct _SquidConfig {
        acl_access *AlwaysDirect;
        acl_access *ASlists;
        acl_access *noCache;
+#if SQUID_SNMP
+       acl_access *snmp;
+#endif
     } accessList;
     acl_deny_info_list *denyInfoList;
     char *proxyAuthRealm;
index 14cbd972f3ddb314b30b8225f578b003103e0ad4..3d98d5d30cc28d2c5b0f5eafc1d3335bc3e06853 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: typedefs.h,v 1.80 1998/10/15 17:34:34 wessels Exp $
+ * $Id: typedefs.h,v 1.81 1998/11/11 20:04:21 glenn Exp $
  *
  *
  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
@@ -163,10 +163,8 @@ typedef struct _helper_request helper_request;
 typedef struct _generic_cbdata generic_cbdata;
 
 #if SQUID_SNMP
+typedef variable_list *(oid_ParseFn) (variable_list *, snint *);
 typedef struct _snmp_request_t snmp_request_t;
-typedef struct _viewEntry viewEntry;
-typedef struct _communityEntry communityEntry;
-typedef struct _usecEntry usecEntry;
 #endif
 
 /* define AIOCB even without USE_ASYNC_IO */