Logo
Home page Net-SNMP

Archive Search:

Require all words?

Site Search:
Google
snmp_agent.c File Reference
Main Page   Data Structures   File List   Data Fields   Globals  

snmp_agent.c File Reference

#include <config.h>
#include <sys/types.h>
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/time.h>
#include <time.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <errno.h>
#include <dmalloc.h>
#include "mibincl.h"
#include "snmp_client.h"
#include "snmp_alarm.h"
#include "snmpd.h"
#include "mibgroup/struct.h"
#include "mibgroup/util_funcs.h"
#include "mib_module_config.h"
#include "default_store.h"
#include "system.h"
#include "ds_agent.h"
#include "snmp_agent.h"
#include "vacm.h"
#include "snmp_transport.h"
#include "snmpUDPDomain.h"
#include "snmpCallbackDomain.h"
#include "snmpUnixDomain.h"
#include "snmpTCPDomain.h"
#include "agentx/protocol.h"
#include "agentx/master.h"

Go to the source code of this file.


Data Structures

struct  _agent_nsap
struct  addrCache
struct  agent_set_cache_s
struct  saved_var_data

Defines

#define SNMP_NEED_REQUEST_LIST
#define SNMP_ADDRCACHE_SIZE   10

Typedefs

typedef _agent_nsap agent_nsap
typedef agent_set_cache_s agent_set_cache

Functions

int snmp_check_packet (struct snmp_session *, struct _snmp_transport *, void *, int)
int snmp_check_parse (struct snmp_session *, struct snmp_pdu *, int)
void delete_subtree_cache (struct agent_snmp_session *asp)
int handle_pdu (struct agent_snmp_session *asp)
int wrap_up_request (struct agent_snmp_session *asp, int status)
int check_delayed_request (struct agent_snmp_session *asp)
int handle_getnext_loop (struct agent_snmp_session *asp)
 repeatedly calls getnext handlers looking for an answer till all requests are satisified. More...

int handle_set_loop (struct agent_snmp_session *asp)
agent_set_cachesave_set_cache (struct agent_snmp_session *asp)
void get_set_cache (struct agent_snmp_session *asp)
int getNextSessID ()
int agent_check_and_process (int block)
void snmp_addrcache_initialise (void)
void snmp_addrcache_age (void)
int snmp_check_packet (struct snmp_session *session, snmp_transport *transport, void *transport_data, int transport_data_length)
int register_agent_nsap (snmp_transport *t)
void deregister_agent_nsap (int handle)
int init_master_agent (void)
agent_snmp_sessioninit_agent_snmp_session (struct snmp_session *session, struct snmp_pdu *pdu)
void free_agent_snmp_session (struct agent_snmp_session *asp)
int check_for_delegated (struct agent_snmp_session *asp)
void dump_sess_list (void)
void remove_and_free_agent_snmp_session (struct agent_snmp_session *asp)
void free_agent_snmp_session_by_session (struct snmp_session *sess, void(*free_request)(struct request_list *))
int handle_snmp_packet (int op, struct snmp_session *session, int reqid, struct snmp_pdu *pdu, void *magic)
 handles an incoming SNMP packet into the agent. More...

int add_varbind_to_cache (struct agent_snmp_session *asp, int vbcount, struct variable_list *varbind_ptr, struct subtree *tp)
int check_acm (struct agent_snmp_session *asp, u_char type)
int create_subtree_cache (struct agent_snmp_session *asp)
int reassign_requests (struct agent_snmp_session *asp)
void delete_request_infos (request_info *reqlist)
int check_requests_status (struct agent_snmp_session *asp, request_info *requests)
int check_all_requests_status (struct agent_snmp_session *asp)
int handle_var_requests (struct agent_snmp_session *asp)
void check_outstanding_agent_requests (int status)
int check_transaction_id (int transaction_id)
 Decide if the requested transaction_id is still being processed within the agent. More...

int check_getnext_results (struct agent_snmp_session *asp)
 returns 1 if there are valid GETNEXT requests left. More...

int handle_set (struct agent_snmp_session *asp)
int set_request_error (agent_request_info *reqinfo, request_info *request, int error_value)
int set_mode_request_error (int mode, request_info *request, int error_value)
int set_all_requests_error (agent_request_info *reqinfo, request_info *requests, int error_value)
int marker_uptime (marker_t pm)
int timeval_uptime (struct timeval *tv)
int get_agent_uptime (void)
void agent_add_list_data (agent_request_info *ari, data_list *node)
void * agent_get_list_data (agent_request_info *ari, const char *name)
void free_agent_data_set (agent_request_info *ari)
void free_agent_data_sets (agent_request_info *ari)
void free_agent_request_info (agent_request_info *ari)

Variables

int lastAddrAge = 0
int log_addresses = 0
agent_snmp_sessionagent_delegated_list = NULL
snmp_session * main_session = NULL
timeval starttime

Define Documentation

#define SNMP_ADDRCACHE_SIZE   10
 

Definition at line 112 of file snmp_agent.c.

#define SNMP_NEED_REQUEST_LIST
 

Definition at line 72 of file snmp_agent.c.


Typedef Documentation

typedef struct _agent_nsap agent_nsap
 

typedef struct agent_set_cache_s agent_set_cache
 


Function Documentation

int add_varbind_to_cache struct agent_snmp_session   asp,
int    vbcount,
struct variable_list *    varbind_ptr,
struct subtree   tp
 

Definition at line 1125 of file snmp_agent.c.

Referenced by create_subtree_cache(), and reassign_requests().

01126                                                                             {
01127     request_info *request;
01128     int cacheid;
01129     tree_cache *tmpc;
01130 
01131     if (tp == NULL) {
01132         /* no appropriate registration found */
01133         /* make up the response ourselves */
01134         switch(asp->pdu->command) {
01135             case SNMP_MSG_GETNEXT:
01136             case SNMP_MSG_GETBULK:
01137                 varbind_ptr->type = SNMP_ENDOFMIBVIEW;
01138                 break;
01139                     
01140             case SNMP_MSG_SET:
01141                 return SNMP_NOSUCHOBJECT;
01142 
01143             case SNMP_MSG_GET:
01144                 varbind_ptr->type = SNMP_NOSUCHOBJECT;
01145                 break;
01146 
01147             default:
01148                 return SNMPERR_GENERR; /* shouldn't get here */
01149         }
01150     } else {
01151         if (!MODE_IS_SET(asp->pdu->command))
01152             varbind_ptr->type = ASN_NULL;
01153 
01154         /* malloc the request structure */
01155         request = SNMP_MALLOC_TYPEDEF(request_info);
01156         if (request == NULL)
01157             return SNMP_ERR_GENERR;
01158         request->index = vbcount;
01159 
01160         /* place them in a cache */
01161         if (tp->cacheid > -1 && tp->cacheid <= asp->treecache_num &&
01162             asp->treecache[tp->cacheid]->subtree == tp) {
01163             /* we have already added a request to this tree
01164                    pointer before */
01165                                         cacheid = tp->cacheid;
01166 
01167         } else {
01168             cacheid = ++(asp->treecache_num);
01169             /* new slot needed */
01170             if (asp->treecache_num >= asp->treecache_len) {
01171                 /* exapand cache array */
01172                 /* WWW: non-linear expansion needed (with cap) */
01173                 asp->treecache_len = (asp->treecache_len + 16);
01174                 asp->treecache = realloc(asp->treecache,
01175                                          sizeof(tree_cache *) *
01176                                          asp->treecache_len);
01177                 if (asp->treecache == NULL)
01178                     return SNMP_ERR_GENERR;
01179             }
01180             tmpc = (tree_cache *) calloc(1, sizeof(tree_cache));
01181             asp->treecache[cacheid] = tmpc;
01182             asp->treecache[cacheid]->subtree = tp;
01183             asp->treecache[cacheid]->requests_begin = request;
01184             tp->cacheid = cacheid;
01185         }
01186 
01187         /* if this is a search type, get the ending range oid as well */
01188         if (asp->pdu->command == SNMP_MSG_GETNEXT ||
01189             asp->pdu->command == SNMP_MSG_GETBULK) {
01190             request->range_end     = tp->end;
01191             request->range_end_len = tp->end_len;
01192         }
01193 
01194         /* link into chain */
01195         if (asp->treecache[cacheid]->requests_end)
01196             asp->treecache[cacheid]->requests_end->next = request;
01197         request->prev =
01198             asp->treecache[cacheid]->requests_end;
01199         asp->treecache[cacheid]->requests_end = request;
01200 
01201         /* add the given request to the list of requests they need
01202                to handle results for */
01203         request->requestvb = varbind_ptr;
01204     }
01205     return SNMP_ERR_NOERROR;
01206 }

void agent_add_list_data agent_request_info   agent,
data_list *    node
[inline]
 

Definition at line 1939 of file snmp_agent.c.

01940 {
01941   if (ari) {
01942     if (ari->agent_data)
01943       add_list_data(&ari->agent_data, node);
01944     else
01945       ari->agent_data = node;
01946   }
01947 }

int agent_check_and_process int    block
 

Definition at line 256 of file snmp_agent.c.

00256                                    {
00257   int numfds;
00258   fd_set fdset;
00259   struct timeval timeout = { LONG_MAX, 0 }, *tvp = &timeout;
00260   int count;
00261   int fakeblock=0;
00262   
00263   numfds = 0;
00264   FD_ZERO(&fdset);
00265   snmp_select_info(&numfds, &fdset, tvp, &fakeblock);
00266   if (block != 0 && fakeblock != 0) {
00267     /*  There are no alarms registered, and the caller asked for blocking, so
00268         let select() block forever.  */
00269 
00270     tvp = NULL;
00271   } else if (block != 0 && fakeblock == 0) {
00272     /*  The caller asked for blocking, but there is an alarm due sooner than
00273         LONG_MAX seconds from now, so use the modified timeout returned by
00274         snmp_select_info as the timeout for select().  */
00275 
00276   } else if (block == 0) {
00277     /*  The caller does not want us to block at all.  */
00278 
00279     tvp->tv_sec  = 0;
00280     tvp->tv_usec = 0;
00281   }
00282 
00283   count = select(numfds, &fdset, 0, 0, tvp);
00284 
00285   if (count > 0) {
00286     /* packets found, process them */
00287     snmp_read(&fdset);
00288   } else switch(count) {
00289     case 0:
00290       snmp_timeout();
00291       break;
00292     case -1:
00293       if (errno != EINTR) {
00294         snmp_log_perror("select");
00295       }
00296       return -1;
00297     default:
00298       snmp_log(LOG_ERR, "select returned %d\n", count);
00299       return -1;
00300   }  /* endif -- count>0 */
00301 
00302   /*  Run requested alarms.  */
00303   run_alarms();
00304 
00305   return count;
00306 }

void* agent_get_list_data agent_request_info   agent,
const char *    name
[inline]
 

Definition at line 1950 of file snmp_agent.c.

01951 {
01952   if (ari)
01953     return get_list_data(ari->agent_data,name);
01954   return NULL;
01955 }

int check_acm struct agent_snmp_session   asp,
u_char    type
 

Definition at line 1214 of file snmp_agent.c.

Referenced by handle_getnext_loop(), and handle_pdu().

01214                                                         {
01215     int view;
01216     int i;
01217     request_info *request;
01218     int ret = 0;
01219     struct variable_list *vb;
01220     
01221     for(i = 0; i <= asp->treecache_num; i++) {
01222         for(request = asp->treecache[i]->requests_begin;
01223             request; request = request->next) {
01224             /* for each request, run it through in_a_view() */
01225             vb = request->requestvb;
01226             if (vb->type == ASN_NULL) /* not yet processed */
01227                 continue;
01228             view = in_a_view(vb->name, &vb->name_length, asp->pdu, vb->type);
01229 
01230             /* if a ACM error occurs, mark it as type passed in */
01231             if (view != VACM_SUCCESS) {
01232                 ret++;
01233                 snmp_set_var_typed_value(vb, type, NULL, 0);
01234             }
01235         }
01236     }
01237     return ret;
01238 }

int check_all_requests_status struct agent_snmp_session   asp
 

Definition at line 1396 of file snmp_agent.c.

Referenced by check_delayed_request().

01396                                                            {
01397     int i;
01398     for(i = 0; i <= asp->treecache_num; i++) {
01399         check_requests_status(asp, asp->treecache[i]->requests_begin);
01400     }
01401     return asp->status;
01402 }

int check_delayed_request struct agent_snmp_session   asp
 

Definition at line 1501 of file snmp_agent.c.

Referenced by check_outstanding_agent_requests().

01501                                                        {
01502     int status = SNMP_ERR_NOERROR;
01503     
01504     check_all_requests_status(asp); /* update the asp->status */
01505 
01506     switch(asp->mode) {
01507         case SNMP_MSG_GETNEXT:
01508             handle_getnext_loop(asp);
01509             break;
01510 
01511         case SNMP_MSG_GETBULK:
01512             /* WWW */
01513             break;
01514 
01515         case MODE_SET_BEGIN:
01516         case MODE_SET_RESERVE1:
01517         case MODE_SET_RESERVE2:
01518         case MODE_SET_ACTION:
01519         case MODE_SET_COMMIT:
01520         case MODE_SET_FREE:
01521         case MODE_SET_UNDO:
01522             handle_set_loop(asp);
01523             if (asp->mode != FINISHED_SUCCESS &&
01524                 asp->mode != FINISHED_FAILURE) {
01525 
01526                 if (check_for_delegated(asp)) {
01527                     /* add to delegated request chain */
01528                     if (!asp->status)
01529                         asp->status = status;
01530                     asp->next = agent_delegated_list;
01531                     agent_delegated_list = asp;
01532                 }
01533 
01534                 return SNMP_ERR_NOERROR;
01535             }
01536             break;
01537 
01538         default:
01539             break;
01540     }
01541 
01542     /* if we don't have anything outstanding (delegated), wrap up */
01543     if (!check_for_delegated(asp))
01544         return wrap_up_request(asp, status);
01545 
01546     return 1;
01547 }

int check_for_delegated struct agent_snmp_session   asp
 

Definition at line 858 of file snmp_agent.c.

Referenced by check_delayed_request(), check_outstanding_agent_requests(), handle_getnext_loop(), handle_set_loop(), and handle_snmp_packet().

00858                                                     {
00859     int i;
00860     request_info *request;
00861     
00862     for(i = 0; i <= asp->treecache_num; i++) {
00863         for(request = asp->treecache[i]->requests_begin; request;
00864             request = request->next) {
00865             if (request->delegated)
00866                 return 1;
00867         }
00868     }
00869     return 0;
00870 }

int check_getnext_results struct agent_snmp_session   asp
 

returns 1 if there are valid GETNEXT requests left.

Returns 0 if not.

Definition at line 1551 of file snmp_agent.c.

Referenced by handle_getnext_loop().

01551                                                        {
01552     /* get old info */
01553     tree_cache **old_treecache = asp->treecache;
01554     int old_treecache_num = asp->treecache_num;
01555     int count = 0;
01556     int i;
01557     request_info *request;
01558     
01559     for(i = 0; i <= old_treecache_num; i++) {
01560         for(request = old_treecache[i]->requests_begin; request;
01561             request = request->next) {
01562 
01563             /* out of range? */
01564             if (snmp_oid_compare(request->requestvb->name,
01565                                  request->requestvb->name_length,
01566                                  request->range_end,
01567                                  request->range_end_len) > 0) {
01568                 /* ack, it's beyond the accepted end of range. */
01569                 /* fix it by setting the oid to the end of range oid instead */
01570                 DEBUGMSGTL(("check_getnext_results",
01571                             "request response %d out of range", request->index));
01572                 
01573                 snmp_set_var_objid(request->requestvb,
01574                                    request->range_end, request->range_end_len);
01575                 snmp_set_var_typed_value(request->requestvb, ASN_NULL,
01576                                          NULL, 0);
01577             }
01578 
01579             /* mark any existent requests with illegal results as NULL */
01580             if (request->requestvb->type == SNMP_ENDOFMIBVIEW) {
01581                 /* illegal response from a subagent.  Change it back to NULL */
01582                 request->requestvb->type = ASN_NULL;
01583             }
01584                             
01585             if (request->requestvb->type == ASN_NULL ||
01586                 request->requestvb->type == ASN_PRIV_RETRY)
01587                 count++;
01588         }
01589     }
01590     return count;
01591 }

void check_outstanding_agent_requests int    status
 

Definition at line 1455 of file snmp_agent.c.

01455                                              {
01456     struct agent_snmp_session *asp, *prev_asp = NULL, *next_asp = NULL;
01457 
01458     for(asp = agent_delegated_list; asp; prev_asp = asp, asp = next_asp) {
01459         next_asp = asp->next; /* save in case we clean up asp */
01460         if (!check_for_delegated(asp)) {
01461 
01462             /* we're done with this one, remove from queue */
01463             if (prev_asp != NULL)
01464                 prev_asp->next = asp->next;
01465             else
01466                 agent_delegated_list = asp->next;
01467 
01468             /* continue processing or finish up */
01469             check_delayed_request(asp);
01470         }
01471     }
01472 }

int check_requests_status struct agent_snmp_session   asp,
request_info   requests
 

Definition at line 1381 of file snmp_agent.c.

Referenced by check_all_requests_status(), and handle_var_requests().

01381                                                                                {
01382     /* find any errors marked in the requests */
01383     while(requests) {
01384         if (requests->status != SNMP_ERR_NOERROR &&
01385             (asp->index == 0 ||
01386              requests->index < asp->index)) {
01387             asp->index = requests->index;
01388             asp->status = requests->status;
01389         }
01390         requests = requests->next;
01391     }
01392     return asp->status;
01393 }

int check_transaction_id int    transaction_id
 

Decide if the requested transaction_id is still being processed within the agent.

This is used to validate whether a delayed cache (containing possibly freed pointers) is still usable.

returns SNMPERR_SUCCESS if it's still valid, or SNMPERR_GENERR if not.

Definition at line 1480 of file snmp_agent.c.

01481 {
01482     struct agent_snmp_session *asp, *prev_asp = NULL;
01483 
01484     for(asp = agent_delegated_list; asp; prev_asp = asp, asp = asp->next) {
01485         if (asp->pdu->transid == transaction_id)
01486             return SNMPERR_SUCCESS;
01487     }
01488     return SNMPERR_GENERR;
01489 }

int create_subtree_cache struct agent_snmp_session   asp
 

Definition at line 1242 of file snmp_agent.c.

Referenced by handle_pdu().

01242                                                       {
01243     struct subtree *tp;
01244     struct variable_list *varbind_ptr;
01245     int ret;
01246     int view;
01247     int vbcount = 0;
01248 
01249     if (asp->treecache == NULL &&
01250         asp->treecache_len == 0) {
01251         asp->treecache_len = 16;
01252         asp->treecache = malloc(sizeof(tree_cache *) * asp->treecache_len);
01253         if (asp->treecache == NULL)
01254             return SNMP_ERR_GENERR;
01255     }
01256     asp->treecache_num = -1;
01257 
01258     /* collect varbinds into their registered trees */
01259 
01260     for(varbind_ptr = asp->start; varbind_ptr;
01261         varbind_ptr = varbind_ptr->next_variable) {
01262 
01263         /* count the varbinds */
01264         ++vbcount;
01265         
01266         if (varbind_ptr->type != ASN_NULL &&  /* skip previously answered */
01267             !(MODE_IS_SET(asp->pdu->command)))
01268             continue;
01269 
01270         /* find the owning tree */
01271         tp = find_subtree(varbind_ptr->name, varbind_ptr->name_length, NULL,
01272                           asp->pdu->contextName); /* WWW: only v3 pdu's have */
01273 
01274         /* check access control */
01275         switch(asp->pdu->command) {
01276             case SNMP_MSG_GET:
01277                 view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length,
01278                                  asp->pdu, varbind_ptr->type);
01279                 if (view != VACM_SUCCESS)
01280                     snmp_set_var_typed_value(varbind_ptr, SNMP_NOSUCHOBJECT,
01281                                              NULL, 0);
01282                 break;
01283 
01284             case SNMP_MSG_SET:
01285                 view = in_a_view(varbind_ptr->name, &varbind_ptr->name_length,
01286                                  asp->pdu, varbind_ptr->type);
01287                 if (view != VACM_SUCCESS)
01288                     return SNMP_ERR_NOTWRITABLE;
01289                 break;
01290 
01291             case SNMP_MSG_GETNEXT:
01292             default:
01293                 view = VACM_SUCCESS;
01294                 /* WWW: check VACM here to see if "tp" is even worthwhile */
01295         }
01296         if (view == VACM_SUCCESS) {
01297             ret = add_varbind_to_cache(asp, vbcount, varbind_ptr, tp);
01298             if (ret != SNMP_ERR_NOERROR)
01299                 return ret;
01300         }
01301     }
01302 
01303     return SNMPERR_SUCCESS;
01304 }

void delete_request_infos request_info   reqlist
 

Definition at line 1357 of file snmp_agent.c.

Referenced by delete_subtree_cache().

01357                                             {
01358     request_info *saveit;
01359     while(reqlist) {
01360         /* don't delete varbind */
01361         saveit = reqlist;
01362         reqlist = reqlist->next;
01363         if (saveit->parent_data)
01364             free_all_list_data(saveit->parent_data);
01365         free(saveit);
01366     }
01367 }

void delete_subtree_cache struct agent_snmp_session   asp
 

Definition at line 1370 of file snmp_agent.c.

Referenced by free_agent_snmp_session().

01370                                                       {
01371     while(asp->treecache_num >= 0) {
01372         /* don't delete subtrees */
01373         delete_request_infos(asp->treecache[asp->treecache_num]
01374                              ->requests_begin);
01375         free(asp->treecache[asp->treecache_num]);
01376         asp->treecache_num--;
01377     }
01378 }

void deregister_agent_nsap int    handle
 

Definition at line 580 of file snmp_agent.c.

00581 {
00582   agent_nsap *a = NULL, **prevNext = &agent_nsap_list;
00583   int main_session_deregistered = 0;
00584 
00585   DEBUGMSGTL(("deregister_agent_nsap", "handle %d\n", handle));
00586 
00587   for (a = agent_nsap_list; a != NULL && a->handle < handle; a = a->next) {
00588     prevNext = &(a->next);
00589   }
00590 
00591   if (a != NULL && a->handle == handle) {
00592     *prevNext = a->next;
00593     if (main_session == snmp_sess_session(a->s)) {
00594       main_session_deregistered = 1;
00595     }
00596     snmp_close(snmp_sess_session(a->s));
00597     /*  The above free()s the transport and session pointers.  */
00598     free(a);
00599   }
00600 
00601   /*  If we've deregistered the session that main_session used to point to,
00602       then make it point to another one, or in the last resort, make it equal
00603       to NULL.  Basically this shouldn't ever happen in normal operation
00604       because main_session starts off pointing at the first session added by
00605       init_master_agent(), which then discards the handle.  */
00606 
00607   if (main_session_deregistered) {
00608     if (agent_nsap_list != NULL) {
00609       DEBUGMSGTL(("snmp_agent",
00610                   "WARNING: main_session pointer changed from %p to %p\n",
00611                   main_session, snmp_sess_session(agent_nsap_list->s)));
00612       main_session = snmp_sess_session(agent_nsap_list->s);
00613     } else {
00614       DEBUGMSGTL(("snmp_agent",
00615                   "WARNING: main_session pointer changed from %p to NULL\n",
00616                   main_session));
00617       main_session = NULL;
00618     }
00619   }
00620 }

void dump_sess_list void   
 

Definition at line 972 of file snmp_agent.c.

00973 {
00974     struct agent_snmp_session *a;
00975     
00976     DEBUGMSGTL(("snmp_agent", "DUMP agent_sess_list -> "));
00977     for (a = agent_session_list; a != NULL; a = a->next) {
00978         DEBUGMSG(("snmp_agent", "%08p[session %08p] -> ", a, a->session));
00979     }
00980     DEBUGMSG(("snmp_agent", "[NIL]\n"));
00981 }

void free_agent_data_set agent_request_info   agent [inline]
 

Definition at line 1958 of file snmp_agent.c.

01959 {
01960   if (ari)
01961     free_list_data(ari->agent_data);
01962 }

void free_agent_data_sets agent_request_info   agent [inline]
 

Definition at line 1965 of file snmp_agent.c.

01966 {
01967   if (ari)
01968     free_all_list_data(ari->agent_data);
01969 }

void free_agent_request_info agent_request_info   ari [inline]
 

Definition at line 1972 of file snmp_agent.c.

01973 {
01974     if (ari) {
01975         if (ari->agent_data)
01976             free_all_list_data(ari->agent_data);
01977         free(ari);
01978     }
01979 }

void free_agent_snmp_session struct agent_snmp_session   asp
 

Definition at line 840 of file snmp_agent.c.

00841 {
00842     if (!asp)
00843         return;
00844     if (asp->orig_pdu)
00845         snmp_free_pdu(asp->orig_pdu);
00846     if (asp->pdu)
00847         snmp_free_pdu(asp->pdu);
00848     if (asp->reqinfo)
00849         free_agent_request_info(asp->reqinfo);
00850     if (asp->treecache) {
00851         delete_subtree_cache(asp);
00852         free(asp->treecache);
00853     }
00854     free(asp);
00855 }

void free_agent_snmp_session_by_session struct snmp_session *    sess,
void(*    free_request)(struct request_list *)
 

Definition at line 1009 of file snmp_agent.c.

01011 {
01012     struct agent_snmp_session *a, *next, **prevNext = &agent_session_list;
01013 
01014     DEBUGMSGTL(("snmp_agent", "REMOVE session == %08p\n", sess));
01015 
01016     for (a = agent_session_list; a != NULL; a = next) {
01017         if (a->session == sess) {
01018             *prevNext = a->next;
01019             next = a->next;
01020             free_agent_snmp_session(a);
01021         } else {
01022             prevNext = &(a->next);
01023             next = a->next;
01024         }
01025     }
01026 }

int getNextSessID void   
 

Definition at line 248 of file snmp_agent.c.

00249 {
00250     static int SessionID = 0;
00251 
00252     return ++SessionID;
00253 }

int get_agent_uptime void   
 

Definition at line 1928 of file snmp_agent.c.

01928                          {
01929 
01930         struct timeval now;
01931         gettimeofday(&now, NULL);
01932 
01933         return timeval_uptime( &now );
01934 }

void get_set_cache struct agent_snmp_session   asp
 

Definition at line 219 of file snmp_agent.c.

Referenced by handle_pdu().

00220 {
00221     agent_set_cache *ptr, *prev=NULL;
00222 
00223     for ( ptr=Sets ; ptr != NULL ; ptr=ptr->next ) {
00224         if ( ptr->sess == asp->session && ptr->transID == asp->pdu->transid ) {
00225             if ( prev )
00226                 prev->next = ptr->next;
00227             else
00228                 Sets = ptr->next;
00229 
00230             /* found it.  Get the needed data */
00231             asp->treecache           = ptr->treecache;
00232             asp->treecache_len       = ptr->treecache_len;
00233             asp->treecache_num       = ptr->treecache_num;
00234             if (!asp->reqinfo) {
00235                 asp->reqinfo = SNMP_MALLOC_TYPEDEF(agent_request_info);
00236                 if (asp->reqinfo) {
00237                     asp->reqinfo->asp = asp;
00238                     asp->reqinfo->agent_data = ptr->agent_data;
00239                 }
00240             }
00241             free(ptr);
00242             return;
00243         }
00244         prev = ptr;
00245     }
00246 }

int handle_getnext_loop struct agent_snmp_session   asp
 

repeatedly calls getnext handlers looking for an answer till all requests are satisified.

It's expected that one pass has been made before entering this function

Definition at line 1597 of file snmp_agent.c.

Referenced by check_delayed_request(), and handle_pdu().

01597                                                      {
01598     int status;
01599     struct variable_list *var_ptr;
01600     int count;
01601 
01602     /* loop */
01603     while (1) {
01604 
01605         /* bail for now if anything is delegated. */
01606         if (check_for_delegated(asp)) {
01607                 return SNMP_ERR_NOERROR;
01608         }
01609 
01610         /* check vacm against results */
01611         check_acm(asp, ASN_PRIV_RETRY);
01612 
01613         /* need to keep going we're not done yet. */
01614         if (!check_getnext_results(asp))
01615             /* nothing left, quit now */
01616             break;
01617             
01618         /* never had a request (empty pdu), quit now */
01619         /* XXXWWW: huh?  this would be too late, no?  shouldn't we
01620            catch this earlier? */
01621 /*        if (count == 0)
01622           break; */
01623         
01624         DEBUGIF("results") {
01625             DEBUGMSGTL(("results","getnext results, before next pass: \n"));
01626             for(var_ptr = asp->pdu->variables; var_ptr;
01627                 var_ptr = var_ptr->next_variable) {
01628                 char buf[SPRINT_MAX_LEN];
01629                 sprint_variable(buf, var_ptr->name, var_ptr->name_length, var_ptr);
01630                 DEBUGMSGTL(("results","  %s\n", buf));
01631             }
01632         }
01633 
01634         reassign_requests(asp);
01635         status = handle_var_requests(asp);
01636         if (status != SNMP_ERR_NOERROR) {
01637             return status; /* should never really happen */
01638         }
01639     }
01640     return SNMP_ERR_NOERROR;
01641 }

int handle_pdu struct agent_snmp_session   asp
 

Definition at line 1738 of file snmp_agent.c.

Referenced by handle_snmp_packet().

01738                                             {
01739     int status;
01740 
01741     /* for illegal requests, mark all nodes as ASN_NULL */
01742     switch(asp->pdu->command) {
01743 
01744         case SNMP_MSG_INTERNAL_SET_RESERVE2:
01745         case SNMP_MSG_INTERNAL_SET_ACTION:
01746         case SNMP_MSG_INTERNAL_SET_COMMIT:
01747         case SNMP_MSG_INTERNAL_SET_FREE:
01748         case SNMP_MSG_INTERNAL_SET_UNDO:
01749             get_set_cache(asp);
01750             break;
01751 
01752         case SNMP_MSG_GET:
01753         case SNMP_MSG_GETNEXT:
01754         case SNMP_MSG_GETBULK:
01755             snmp_reset_var_types(asp->pdu->variables, ASN_NULL);
01756             /* fall through */
01757 
01758         case SNMP_MSG_INTERNAL_SET_BEGIN:
01759         case SNMP_MSG_INTERNAL_SET_RESERVE1:
01760         default:
01761             /* collect varbinds */
01762             status = create_subtree_cache(asp);
01763             if (status != SNMP_ERR_NOERROR)
01764                 return status;
01765     }
01766     
01767     asp->mode = asp->pdu->command;
01768     switch(asp->mode) {
01769         case SNMP_MSG_GET:
01770             /* increment the message type counter */
01771             snmp_increment_statistic(STAT_SNMPINGETREQUESTS);
01772 
01773             /* check vacm ahead of time */
01774             check_acm(asp, SNMP_NOSUCHOBJECT);
01775                 
01776             /* get the results */
01777             status = handle_var_requests(asp);
01778 
01779             /* deal with unhandled results -> noSuchObject */
01780             if (status == SNMP_ERR_NOERROR)
01781                 snmp_replace_var_types(asp->pdu->variables, ASN_NULL,
01782                                        SNMP_NOSUCHOBJECT);
01783             break;
01784 
01785         case SNMP_MSG_GETNEXT:
01786             /* increment the message type counter */
01787             snmp_increment_statistic(STAT_SNMPINGETNEXTS);
01788 
01789             /* loop through our mib tree till we find an
01790                appropriate response to return to the caller. */
01791 
01792             /* first pass */
01793             status = handle_var_requests(asp);
01794             if (status != SNMP_ERR_NOERROR) {
01795                 return status; /* should never really happen */
01796             }
01797 
01798             handle_getnext_loop(asp);
01799             break;
01800 
01801         case SNMP_MSG_SET:
01802             /* check access permissions first */
01803             if (check_acm(asp, SNMP_NOSUCHOBJECT))
01804                 return SNMP_ERR_NOTWRITABLE;
01805 
01806             asp->mode = MODE_SET_BEGIN;
01807             status = handle_set_loop(asp);
01808             
01809             break;
01810 
01811         case SNMP_MSG_INTERNAL_SET_BEGIN:
01812         case SNMP_MSG_INTERNAL_SET_RESERVE1:
01813         case SNMP_MSG_INTERNAL_SET_RESERVE2:
01814         case SNMP_MSG_INTERNAL_SET_ACTION:
01815         case SNMP_MSG_INTERNAL_SET_COMMIT:
01816         case SNMP_MSG_INTERNAL_SET_FREE:
01817         case SNMP_MSG_INTERNAL_SET_UNDO:
01818             asp->pdu->flags |= UCD_MSG_FLAG_ONE_PASS_ONLY;
01819             status = handle_set_loop(asp);
01820             /* asp related cache is saved in cleanup */
01821             break;
01822 
01823         case SNMP_MSG_GETBULK:
01824             break;
01825             /* WWW */
01826 
01827         case SNMP_MSG_RESPONSE:
01828             snmp_increment_statistic(STAT_SNMPINGETRESPONSES);
01829             return SNMP_ERR_NOERROR;
01830             
01831         case SNMP_MSG_TRAP:
01832         case SNMP_MSG_TRAP2:
01833             snmp_increment_statistic(STAT_SNMPINTRAPS);
01834             return SNMP_ERR_NOERROR;
01835             
01836         default:
01837             /* WWW: are reports counted somewhere ? */
01838             snmp_increment_statistic(STAT_SNMPINASNPARSEERRS);
01839             return SNMPERR_GENERR; /* shouldn't get here */
01840             /* WWW */
01841     }
01842     return status;
01843 }

int handle_set struct agent_snmp_session   asp
 

Definition at line 1644 of file snmp_agent.c.

Referenced by handle_set_loop().

01644                                             {
01645     int status;
01646     /*
01647      * SETS require 3-4 passes through the var_op_list.
01648      * The first two
01649      * passes verify that all types, lengths, and values are valid
01650      * and may reserve resources and the third does the set and a
01651      * fourth executes any actions.  Then the identical GET RESPONSE
01652      * packet is returned.
01653      * If either of the first two passes returns an error, another
01654      * pass is made so that any reserved resources can be freed.
01655      * If the third pass returns an error, another pass is
01656      * made so that
01657      * any changes can be reversed.
01658      * If the fourth pass (or any of the error handling passes)
01659      * return an error, we'd rather not know about it!
01660      */
01661     if (!(asp->pdu->flags & UCD_MSG_FLAG_ONE_PASS_ONLY)) {
01662         switch (asp->mode) {
01663             case MODE_SET_BEGIN:
01664                 snmp_increment_statistic(STAT_SNMPINSETREQUESTS);
01665                 asp->rw      = WRITE; /* WWW: still needed? */
01666                 asp->mode = MODE_SET_RESERVE1;
01667                 asp->status = SNMP_ERR_NOERROR;
01668                 break;
01669             
01670             case MODE_SET_RESERVE1:
01671 
01672                 if ( asp->status != SNMP_ERR_NOERROR )
01673                     asp->mode = MODE_SET_FREE;
01674                 else
01675                     asp->mode = MODE_SET_RESERVE2;
01676                 break;
01677 
01678             case MODE_SET_RESERVE2:
01679                 if ( asp->status != SNMP_ERR_NOERROR )
01680                     asp->mode = MODE_SET_FREE;
01681                 else
01682                     asp->mode = MODE_SET_ACTION;
01683                 break;
01684 
01685             case MODE_SET_ACTION:
01686                 if ( asp->status != SNMP_ERR_NOERROR )
01687                     asp->mode = MODE_SET_UNDO;
01688                 else
01689                     asp->mode = MODE_SET_COMMIT;
01690                 break;
01691 
01692             case MODE_SET_COMMIT:
01693                 if ( asp->status != SNMP_ERR_NOERROR ) {
01694                     asp->status    = SNMP_ERR_COMMITFAILED;
01695                     asp->mode = FINISHED_FAILURE;
01696                 }
01697                 else
01698                     asp->mode = FINISHED_SUCCESS;
01699                 break;
01700 
01701             case MODE_SET_UNDO:
01702                 if (asp->status != SNMP_ERR_NOERROR )
01703                     asp->status = SNMP_ERR_UNDOFAILED;
01704 
01705                 asp->mode = FINISHED_FAILURE;
01706                 break;
01707 
01708             case MODE_SET_FREE:
01709                 asp->mode = FINISHED_FAILURE;
01710                 break;
01711         }
01712     }
01713     
01714     if (asp->mode != FINISHED_SUCCESS && asp->mode != FINISHED_FAILURE) {
01715         DEBUGMSGTL(("agent_set","doing set mode = %d\n",asp->mode));
01716         status = handle_var_requests( asp );
01717         if (status != SNMP_ERR_NOERROR && asp->status == SNMP_ERR_NOERROR)
01718             asp->status = status;
01719         DEBUGMSGTL(("agent_set","did set mode = %d, status = %d\n",
01720                     asp->mode, asp->status));
01721     }
01722     return asp->status;
01723 }

int handle_set_loop struct agent_snmp_session   asp
 

Definition at line 1726 of file snmp_agent.c.

Referenced by check_delayed_request(), and handle_pdu().

01726                                                  {
01727     while(asp->mode != FINISHED_FAILURE && asp->mode != FINISHED_SUCCESS) {
01728         handle_set(asp);
01729         if (check_for_delegated(asp))
01730             return SNMP_ERR_NOERROR;
01731         if (asp->pdu->flags & UCD_MSG_FLAG_ONE_PASS_ONLY)
01732             return asp->status;
01733     }
01734     return asp->status;
01735 }

int handle_snmp_packet int    op,
struct snmp_session *    session,
int    reqid,
struct snmp_pdu *    pdu,
void *    magic
 

handles an incoming SNMP packet into the agent.

Definition at line 1030 of file snmp_agent.c.

01032 {
01033     struct agent_snmp_session  *asp;
01034     int status, access_ret;
01035     struct variable_list *var_ptr;
01036 
01037     /* we only support receiving here */
01038     if (op != SNMP_CALLBACK_OP_RECEIVED_MESSAGE) {
01039       return 1;
01040     }
01041 
01042     /* new request */
01043     asp = init_agent_snmp_session( session, pdu );
01044     status = SNMP_ERR_NOERROR;
01045 
01046     /* initial access check.  Is request user/community allowed to do
01047        anything at all? If not, abondon all hope here. */
01048     if ((access_ret = check_access(pdu)) != 0) {
01049         if (access_ret == VACM_NOSUCHCONTEXT) {
01050             /* rfc2573 section 3.2, step 5 says that we increment the
01051                counter but don't return a response of any kind */
01052                
01053             /* we currently don't support unavailable contexts, as
01054                there is no reason to that I currently know of */
01055             snmp_increment_statistic(STAT_SNMPUNKNOWNCONTEXTS);
01056 
01057             /* drop the request */
01058             remove_and_free_agent_snmp_session( asp );
01059             return 0;
01060         } else {
01061             /* access control setup is incorrect */
01062             send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
01063             if (asp->pdu->version != SNMP_VERSION_1 &&
01064                 asp->pdu->version != SNMP_VERSION_2c) {
01065                 asp->pdu->errstat = SNMP_ERR_AUTHORIZATIONERROR;
01066                 asp->pdu->command = SNMP_MSG_RESPONSE;
01067                 snmp_increment_statistic(STAT_SNMPOUTPKTS);
01068                 if (! snmp_send( asp->session, asp->pdu ))
01069                     snmp_free_pdu(asp->pdu);
01070                 asp->pdu = NULL;
01071                 remove_and_free_agent_snmp_session(asp);
01072                 return 1;
01073             } else {
01074                 /* drop the request */
01075                 remove_and_free_agent_snmp_session( asp );
01076                 return 0;
01077             }
01078         }
01079     }
01080 
01081     /* process the request */
01082     status = handle_pdu(asp);
01083 
01084     /* print the results in approrpiate debugging mode */
01085     DEBUGIF("results") {
01086         DEBUGMSGTL(("results","request results (status = %d): \n", status));
01087         for(var_ptr = asp->pdu->variables; var_ptr;
01088             var_ptr = var_ptr->next_variable) {
01089             char buf[SPRINT_MAX_LEN];
01090             sprint_variable(buf, var_ptr->name, var_ptr->name_length, var_ptr);
01091             DEBUGMSGTL(("results","  %s\n", buf));
01092         }
01093     }
01094 
01095     /* check for uncompleted requests */
01096     if (check_for_delegated(asp)) {
01097         /* add to delegated request chain */
01098         asp->status = status;
01099         asp->next = agent_delegated_list;
01100         agent_delegated_list = asp;
01101     } else {
01102         /* if we don't have anything outstanding (delegated), wrap up */
01103         return wrap_up_request(asp, status);
01104     }
01105 
01106     /* done */
01107     DEBUGMSGTL(("snmp_agent", "end of handle_snmp_packet, asp = %08p\n", asp));
01108     return 1;
01109 }

int handle_var_requests struct agent_snmp_session   asp
 

Definition at line 1405 of file snmp_agent.c.

Referenced by handle_getnext_loop(), handle_pdu(), and handle_set().

01405                                                      {
01406     int i, retstatus = SNMP_ERR_NOERROR,
01407         status = SNMP_ERR_NOERROR, final_status = SNMP_ERR_NOERROR;
01408     handler_registration *reginfo;
01409 
01410     /* create the agent_request_info data */
01411     if (!asp->reqinfo) {
01412         asp->reqinfo = SNMP_MALLOC_TYPEDEF(agent_request_info);
01413         if (!asp->reqinfo)
01414             return SNMP_ERR_GENERR;
01415     }
01416 
01417     asp->reqinfo->asp = asp;
01418     asp->reqinfo->mode = asp->mode;
01419 
01420     /* now, have the subtrees in the cache go search for their results */
01421     for(i=0; i <= asp->treecache_num; i++) {
01422         reginfo = asp->treecache[i]->subtree->reginfo;
01423         status = call_handlers(reginfo, asp->reqinfo,
01424                                asp->treecache[i]->requests_begin);
01425 
01426         /* find any errors marked in the requests */
01427         retstatus =
01428             check_requests_status(asp, asp->treecache[i]->requests_begin);
01429 
01430         /* always take lowest varbind if possible */
01431         if (retstatus != SNMP_ERR_NOERROR)
01432             status = retstatus;
01433         
01434         /* other things we know less about (no index) */
01435         /* WWW: drop support for this? */
01436         if (final_status == SNMP_ERR_NOERROR &&
01437             status != SNMP_ERR_NOERROR) {
01438             /* we can't break here, since some processing needs to be
01439                done for all requests anyway (IE, SET handling for UNDO
01440                needs to be called regardless of previous status
01441                results.
01442                WWW:  This should be predictable though and
01443                breaking should be possible in some cases (eg GET,
01444                GETNEXT, ...) */
01445             final_status = status;
01446         }
01447     }
01448 
01449    return final_status;
01450 }

struct agent_snmp_session* init_agent_snmp_session struct snmp_session *    session,
struct snmp_pdu *    pdu
 

Definition at line 812 of file snmp_agent.c.

00813 {
00814     struct agent_snmp_session  *asp;
00815 
00816     asp = (struct agent_snmp_session *) calloc(1, sizeof( struct agent_snmp_session ));
00817 
00818     if ( asp == NULL )
00819         return NULL;
00820     asp->session = session;
00821     asp->pdu      = snmp_clone_pdu(pdu);
00822     asp->orig_pdu = snmp_clone_pdu(pdu);
00823     asp->rw      = READ;
00824     asp->exact   = TRUE;
00825     asp->next    = NULL;
00826     asp->mode    = RESERVE1;
00827     asp->status  = SNMP_ERR_NOERROR;
00828     asp->index   = 0;
00829 
00830     asp->start = asp->pdu->variables;
00831     asp->end   = asp->pdu->variables;
00832     if ( asp->end != NULL )
00833         while ( asp->end->next_variable != NULL )
00834             asp->end = asp->end->next_variable;
00835 
00836     return asp;
00837 }

int init_master_agent void   
 

Definition at line 648 of file snmp_agent.c.

Referenced by main().

00649 {
00650   snmp_transport *transport;
00651   char *cptr, *cptr2;
00652   char buf[SPRINT_MAX_LEN];
00653 
00654   if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_ROLE) != MASTER_AGENT) {
00655     DEBUGMSGTL(("snmp_agent", "init_master_agent; not master agent\n"));
00656     return 0; /*  No error if ! MASTER_AGENT  */
00657   }
00658 
00659 #ifdef USING_AGENTX_MASTER_MODULE
00660     if ( ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_AGENTX_MASTER) == 1 )
00661         real_init_master();
00662 #endif
00663 
00664   /*  Have specific agent ports been specified?  */
00665   cptr = ds_get_string(DS_APPLICATION_ID, DS_AGENT_PORTS);
00666 
00667   if (cptr) {
00668     sprintf(buf, "%s", cptr);
00669   } else {
00670     /*  No, so just specify the default port.  */
00671     if (ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS) &
00672         SNMP_FLAGS_STREAM_SOCKET) {
00673       sprintf(buf, "tcp:%d", SNMP_PORT);
00674     } else {
00675       sprintf(buf, "udp:%d", SNMP_PORT);
00676     }
00677   }
00678 
00679   DEBUGMSGTL(("snmp_agent", "final port spec: %s\n", buf));
00680   cptr = strtok(buf, ",");
00681   while (cptr) {
00682     /*  Specification format: 
00683         
00684         NONE:                     (a pseudo-transport)
00685         UDP:[address:]port        (also default if no transport is specified)
00686         TCP:[address:]port        (if supported)
00687         Unix:pathname             (if supported)
00688         AAL5PVC:itf.vpi.vci       (if supported)
00689         IPX:[network]:node[/port] (if supported)
00690 
00691     */
00692 
00693     DEBUGMSGTL(("snmp_agent", "installing master agent on port %s\n", cptr));
00694 
00695     if (!cptr || !(*cptr)) {
00696       snmp_log(LOG_ERR, "improper port specification\n");
00697       return 1;
00698     }
00699 
00700     /*  Transport type specifier?  */
00701 
00702     if ((cptr2 = strchr(cptr, ':')) != NULL) {
00703       if (strncasecmp(cptr, "none", 4) == 0) {
00704         DEBUGMSGTL(("snmp_agent",
00705                  "init_master_agent; pseudo-transport \"none\" requested\n"));
00706         return 0;
00707       } else if (strncasecmp(cptr, "tcp", 3) == 0) {
00708 #ifdef SNMP_TRANSPORT_TCP_DOMAIN
00709         struct sockaddr_in addr;
00710         if (snmp_sockaddr_in(&addr, cptr2+1, 0)) {
00711           transport = snmp_tcp_transport(&addr, 1);
00712         } else {
00713           snmp_log(LOG_ERR,
00714                    "Badly formatted IP address (should be [a.b.c.d:]p)\n");
00715           return 1;
00716         }
00717 #else
00718         snmp_log(LOG_ERR, "No support for requested TCP domain\n");
00719         return 1;
00720 #endif
00721       } else if (strncasecmp(cptr, "ipx", 3) == 0) {
00722 #ifdef SNMP_TRANSPORT_IPX_DOMAIN
00723         struct sockaddr_ipx addr;
00724         if (snmp_sockaddr_ipx(&addr, cptr2+1)) {
00725           transport = snmp_ipx_transport(&addr, 1);
00726         } else {
00727           snmp_log(LOG_ERR,
00728                "Badly formatted IPX address (should be [net]:node[/port])\n");
00729           return 1;
00730         }
00731 #else
00732         snmp_log(LOG_ERR, "No support for requested IPX domain\n");
00733 #endif
00734       } else if (strncasecmp(cptr, "aal5pvc", 7) == 0) {
00735 #ifdef SNMP_TRANSPORT_AAL5PVC_DOMAIN
00736         struct sockaddr_atmpvc addr;
00737         if (sscanf(cptr2+1, "%d.%d.%d", &(addr.sap_addr.itf),
00738                    &(addr.sap_addr.vpi), &(addr.sap_addr.vci))==3) {
00739           addr.sap_family = AF_ATMPVC;
00740           transport = snmp_aal5pvc_transport(&addr, 1);
00741         } else {
00742           snmp_log(LOG_ERR,
00743                  "Badly formatted AAL5 PVC address (should be itf.vpi.vci)\n");
00744           return 1;
00745         }
00746 #else
00747         snmp_log(LOG_ERR, "No support for requested AAL5 PVC domain\n");
00748         return 1;
00749 #endif
00750       } else if (strncasecmp(cptr, "unix", 4) == 0) {
00751 #ifdef SNMP_TRANSPORT_UNIX_DOMAIN
00752         struct sockaddr_un addr;
00753         addr.sun_family = AF_UNIX;
00754         strncpy(addr.sun_path, cptr2+1, 
00755                 sizeof(addr) - (size_t) (((struct sockaddr_un *)0)->sun_path));
00756         transport = snmp_unix_transport(&addr, 1);
00757 #else
00758         snmp_log(LOG_ERR, "No support for requested Unix domain\n");
00759         return 1;
00760 #endif
00761       } else if (strncasecmp(cptr, "udp", 3) == 0) {
00762         struct sockaddr_in addr;
00763         if (snmp_sockaddr_in(&addr, cptr2+1, 0)) {
00764           transport = snmp_udp_transport(&addr, 1);
00765         } else {
00766           snmp_log(LOG_ERR,
00767                    "Badly formatted IP address (should be [a.b.c.d:]p)\n");
00768           return 1;
00769         }
00770       } else {
00771         snmp_log(LOG_ERR, "Unknown transport domain \"%s\"\n", cptr);
00772         return 1;
00773       }
00774     } else {
00775       /*  No transport type specifier; default to UDP.  */
00776       struct sockaddr_in addr;
00777       if (snmp_sockaddr_in(&addr, cptr, 0)) {
00778         transport = snmp_udp_transport(&addr, 1);
00779       } else {
00780         snmp_log(LOG_ERR,
00781                  "Badly formatted IP address (should be [a.b.c.d:]p)\n");
00782         return 1;
00783       }
00784     }
00785 
00786     if (transport == NULL) {
00787       snmp_log(LOG_ERR, "Error opening specified transport \"%s\"\n", cptr);
00788       return 1;
00789     }
00790 
00791     if (register_agent_nsap(transport) == 0) {
00792       snmp_log(LOG_ERR,
00793              "Error registering specified transport \"%s\" as an agent NSAP\n",
00794                cptr);
00795       return 1;
00796     } else {
00797       DEBUGMSGTL(("snmp_agent",
00798                   "init_master_agent; \"%s\" registered as an agent NSAP\n",
00799                   cptr));
00800     }
00801 
00802     /*  Next transport please...  */
00803     cptr = strtok(NULL, ",");
00804   }
00805 
00806   return 0;
00807 }

int marker_uptime marker_t    pm
 

Definition at line 1911 of file snmp_agent.c.

01912 {
01913     int res;
01914     marker_t start = (marker_t)&starttime;
01915 
01916     res = atime_diff( start, pm );
01917     return res/10;      /* atime_diff works in msec, not csec */
01918 }

int reassign_requests struct agent_snmp_session   asp
 

Definition at line 1308 of file snmp_agent.c.

Referenced by handle_getnext_loop().

01308                                                    {
01309     /* assume all the requests have been filled or rejected by the
01310        subtrees, so reassign the rejected ones to the next subtree in
01311        the chain */
01312 
01313     int i, ret;
01314     request_info *request, *lastreq = NULL;
01315 
01316     /* get old info */
01317     tree_cache **old_treecache = asp->treecache;
01318     int old_treecache_num = asp->treecache_num;
01319 
01320     /* malloc new space */
01321     asp->treecache =
01322         (tree_cache **) malloc(sizeof(tree_cache *) * asp->treecache_len);
01323     asp->treecache_num = -1;
01324 
01325     for(i = 0; i <= old_treecache_num; i++) {
01326         for(request = old_treecache[i]->requests_begin; request;
01327             request = request->next) {
01328 
01329             if (lastreq)
01330                 free(lastreq);
01331             lastreq = request;
01332             
01333             if (request->requestvb->type == ASN_NULL) {
01334                 ret = add_varbind_to_cache(asp, request->index,
01335                                            request->requestvb,
01336                                            old_treecache[i]->subtree->next);
01337                 if (ret != SNMP_ERR_NOERROR)
01338                     return ret; /* WWW: mem leak */
01339             } else if (request->requestvb->type == ASN_PRIV_RETRY) {
01340                 /* re-add the same subtree */
01341                 request->requestvb->type = ASN_NULL;
01342                 ret = add_varbind_to_cache(asp, request->index,
01343                                            request->requestvb,
01344                                            old_treecache[i]->subtree);
01345                 if (ret != SNMP_ERR_NOERROR)
01346                     return ret; /* WWW: mem leak */
01347             }
01348         }
01349     }
01350     if (lastreq)
01351         free(lastreq);
01352     free(old_treecache);
01353     return SNMP_ERR_NOERROR;
01354 }

int register_agent_nsap snmp_transport *    t
 

Definition at line 508 of file snmp_agent.c.

00509 {
00510   struct snmp_session *s, *sp = NULL;
00511   agent_nsap *a = NULL, *n = NULL, **prevNext = &agent_nsap_list;
00512   int handle = 0;
00513   void *isp = NULL;
00514 
00515   if (t == NULL) {
00516     return -1;
00517   }
00518 
00519   DEBUGMSGTL(("register_agent_nsap", "fd %d\n", t->sock));
00520 
00521   n = (agent_nsap *)malloc(sizeof(agent_nsap));
00522   if (n == NULL) {
00523     return -1;
00524   }
00525   s = (struct snmp_session *)malloc(sizeof(struct snmp_session));
00526   if (s == NULL) {
00527     free(n);
00528     return -1;
00529   }
00530   memset(s, 0, sizeof(struct snmp_session));
00531   snmp_sess_init(s);
00532 
00533   /*  Set up the session appropriately for an agent.  */
00534 
00535   s->version         = SNMP_DEFAULT_VERSION;
00536   s->callback        = handle_snmp_packet;
00537   s->authenticator   = NULL;
00538   s->flags           = ds_get_int(DS_APPLICATION_ID, DS_AGENT_FLAGS);
00539   s->isAuthoritative = SNMP_SESS_AUTHORITATIVE;
00540 
00541   sp  = snmp_add(s, t, snmp_check_packet, snmp_check_parse);
00542   if (sp == NULL) {
00543     free(s);
00544     free(n);
00545     return -1;
00546   }
00547 
00548   isp = snmp_sess_pointer(sp);
00549   if (isp == NULL) {    /*  over-cautious  */
00550     free(s);
00551     free(n);
00552     return -1;
00553   }
00554 
00555   n->s    = isp;
00556   n->t    = t;
00557 
00558   if (main_session == NULL) {
00559     main_session = snmp_sess_session(isp);
00560   }
00561 
00562   for (a = agent_nsap_list; a != NULL && handle+1 >= a->handle; a = a->next) {
00563     handle = a->handle;
00564     prevNext = &(a->next);
00565   }
00566 
00567   if (handle < INT_MAX) {
00568     n->handle = handle + 1;
00569     n->next   = a;
00570     *prevNext = n;
00571     free(s);
00572     return n->handle;
00573   } else {
00574     free(s);
00575     free(n);
00576     return -1;
00577   }
00578 }

void remove_and_free_agent_snmp_session struct agent_snmp_session   asp
 

Definition at line 984 of file snmp_agent.c.

00985 {
00986     struct agent_snmp_session *a, **prevNext = &agent_session_list;
00987 
00988     DEBUGMSGTL(("snmp_agent", "REMOVE %08p\n", asp));
00989 
00990     for (a = agent_session_list; a != NULL; a = *prevNext) {
00991         if (a == asp) {
00992             *prevNext = a->next;
00993             a->next = NULL;
00994             free_agent_snmp_session(a);
00995             asp = NULL;
00996             break;
00997         } else {
00998             prevNext = &(a->next);
00999         }
01000     }
01001 
01002     if (a == NULL && asp != NULL) {
01003         /*  We coulnd't find it on the list, so free it anyway.  */
01004         free_agent_snmp_session(asp);
01005     }
01006 }

agent_set_cache* save_set_cache struct agent_snmp_session   asp
 

Definition at line 192 of file snmp_agent.c.

Referenced by wrap_up_request().

00193 {
00194     agent_set_cache *ptr;
00195 
00196     ptr = SNMP_MALLOC_TYPEDEF(agent_set_cache);
00197     if (ptr == NULL )
00198         return NULL;
00199 
00200     /* Save the important information */
00201     ptr->transID       = asp->pdu->transid;
00202     ptr->sess          = asp->session;
00203     ptr->treecache     = asp->treecache;
00204     ptr->treecache_len = asp->treecache_len;
00205     ptr->treecache_num = asp->treecache_num;
00206     ptr->agent_data    = asp->reqinfo->agent_data;
00207 
00208     /* make the agent forget about what we've saved */
00209     asp->treecache = NULL;
00210     asp->reqinfo->agent_data = NULL;
00211     
00212     ptr->next = Sets;
00213     Sets = ptr;
00214 
00215     return ptr;
00216 }

int set_all_requests_error agent_request_info   reqinfo,
request_info   requests,
int    error_value
 

Definition at line 1898 of file snmp_agent.c.

01899                                              {
01900     while(requests) {
01901         set_request_error(reqinfo, requests, error_value);
01902         requests = requests->next;
01903     }
01904     return error_value;
01905 }

int set_mode_request_error int    mode,
request_info   request,
int    error_value
 

Definition at line 1853 of file snmp_agent.c.

01854                                         {
01855     if (!request)
01856         return error_value;
01857 
01858     request->processed = 1;
01859 
01860     switch(error_value) {
01861         case SNMP_NOSUCHOBJECT:
01862         case SNMP_NOSUCHINSTANCE:
01863         case SNMP_ENDOFMIBVIEW:
01864             /* these are exceptions that should be put in the varbind
01865                in the case of a GET but should be translated for a SET
01866                into a real error status code and put in the request */
01867             switch (mode) {
01868                 case MODE_GET:
01869                     request->requestvb->type = error_value;
01870                     return error_value;
01871                     
01872                 case MODE_GETNEXT:
01873                 case MODE_GETBULK:
01874                     /* ignore these.  They're illegal to set by the
01875                        client APIs for these modes */
01876                     return error_value;
01877 
01878                 default:
01879                     request->status = SNMP_ERR_NOSUCHNAME; /* WWW: correct? */
01880                     return error_value;
01881             }
01882             break; /* never get here */
01883 
01884         default:
01885             if (request->status < 0) {
01886                 /* illegal local error code.  translate to generr */
01887                 /* WWW: full translation map? */
01888                 request->status = SNMP_ERR_GENERR;
01889             } else {
01890                 /* WWW: translations and mode checking? */
01891                 request->status = error_value;
01892             }
01893             return error_value;
01894     }
01895     return error_value;
01896 }

int set_request_error agent_request_info   reqinfo,
request_info   request,
int    error_value
 

Definition at line 1845 of file snmp_agent.c.

01846                                         {
01847     if (!request || !reqinfo)
01848         return error_value;
01849 
01850     return set_mode_request_error(reqinfo->mode, request, error_value);
01851 }

void snmp_addrcache_age void   
 

Definition at line 325 of file snmp_agent.c.

Referenced by main().

00326 {
00327   int i = 0;
00328   
00329   lastAddrAge = 0;
00330   for (i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00331     if (addrCache[i].status == SNMP_ADDRCACHE_OLD) {
00332       addrCache[i].status = SNMP_ADDRCACHE_UNUSED;
00333       if (addrCache[i].addr != NULL) {
00334         free(addrCache[i].addr);
00335         addrCache[i].addr = NULL;
00336       }
00337     }
00338     if (addrCache[i].status == SNMP_ADDRCACHE_USED) {
00339       addrCache[i].status = SNMP_ADDRCACHE_OLD;
00340     }
00341   }
00342 }

void snmp_addrcache_initialise void   
 

Definition at line 311 of file snmp_agent.c.

Referenced by main().

00312 {
00313   int i = 0;
00314   
00315   for (i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00316     addrCache[i].addr = NULL;
00317     addrCache[i].status = SNMP_ADDRCACHE_UNUSED;
00318   }
00319 }

int snmp_check_packet struct snmp_session *    session,
snmp_transport *    transport,
void *    transport_data,
int    transport_data_length
 

Definition at line 361 of file snmp_agent.c.

00363 {
00364   char *addr_string = NULL;
00365   int i = 0;
00366 
00367   /*
00368    * Log the message and/or dump the message.
00369    * Optionally cache the network address of the sender.
00370    */
00371 
00372   if (transport != NULL && transport->f_fmtaddr != NULL) {
00373     /*  Okay I do know how to format this address for logging.  */
00374     addr_string = transport->f_fmtaddr(transport, transport_data,
00375                                        transport_data_length);
00376     /*  Don't forget to free() it.  */
00377   } else {
00378     /*  Don't know how to format the address for logging.  */
00379     addr_string = strdup("<UNKNOWN>");
00380   }
00381 
00382 #ifdef  USE_LIBWRAP
00383   if (hosts_ctl("snmpd", addr_string, addr_string, STRING_UNKNOWN)) {
00384     snmp_log(allow_severity, "Connection from %s\n", addr_string);
00385   } else {
00386     snmp_log(deny_severity, "Connection from %s REFUSED\n", addr_string);
00387     if (addr_string != NULL) {
00388       free(addr_string);
00389     }
00390     return 0;
00391   }
00392 #endif/*USE_LIBWRAP*/
00393 
00394   snmp_increment_statistic(STAT_SNMPINPKTS);
00395 
00396   if (log_addresses || ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)) {
00397     
00398     for (i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00399       if ((addrCache[i].status != SNMP_ADDRCACHE_UNUSED) &&
00400           (strcmp(addrCache[i].addr, addr_string) == 0)) {
00401         break;
00402       }
00403     }
00404 
00405     if (i >= SNMP_ADDRCACHE_SIZE ||
00406         ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE)){
00407       /*  Address wasn't in the cache, so log the packet...  */
00408       snmp_log(LOG_INFO, "Received SNMP packet(s) from %s\n", addr_string);
00409       /*  ...and try to cache the address.  */
00410       for (i = 0; i < SNMP_ADDRCACHE_SIZE; i++) {
00411         if (addrCache[i].status == SNMP_ADDRCACHE_UNUSED) {
00412           if (addrCache[i].addr != NULL) {
00413             free(addrCache[i].addr);
00414           }
00415           addrCache[i].addr   = addr_string;
00416           addrCache[i].status = SNMP_ADDRCACHE_USED;
00417           addr_string         = NULL;   /* Don't free this 'temporary' string
00418                                            since it's now part of the cache */
00419           break;
00420         }
00421       }
00422       if (i >= SNMP_ADDRCACHE_SIZE) {
00423         /*  We didn't find a free slot to cache the address.  Perhaps we
00424             should be using an LRU replacement policy here or something.  Oh
00425             well.  */
00426         DEBUGMSGTL(("snmp_check_packet", "cache overrun"));
00427       }
00428     } else {
00429       addrCache[i].status = SNMP_ADDRCACHE_USED;
00430     }
00431   }
00432 
00433   if (addr_string != NULL) {
00434     free(addr_string);
00435     addr_string = NULL;
00436   }
00437   return 1;
00438 }

int snmp_check_packet struct snmp_session *   ,
struct _snmp_transport *   ,
void *   ,
int   
 

int snmp_check_parse struct snmp_session *    session,
struct snmp_pdu *    pdu,
int    result
 

Definition at line 441 of file snmp_agent.c.

00443 {
00444   if (result == 0) {
00445     if (ds_get_boolean(DS_APPLICATION_ID, DS_AGENT_VERBOSE) &&
00446         snmp_get_do_logging()) {
00447       struct variable_list *var_ptr;
00448             
00449       switch (pdu->command) {
00450       case SNMP_MSG_GET:
00451         snmp_log(LOG_DEBUG, "  GET message\n"); break;
00452       case SNMP_MSG_GETNEXT:
00453         snmp_log(LOG_DEBUG, "  GETNEXT message\n"); break;
00454       case SNMP_MSG_RESPONSE:
00455         snmp_log(LOG_DEBUG, "  RESPONSE message\n"); break;
00456       case SNMP_MSG_SET:
00457         snmp_log(LOG_DEBUG, "  SET message\n"); break;
00458       case SNMP_MSG_TRAP:
00459         snmp_log(LOG_DEBUG, "  TRAP message\n"); break;
00460       case SNMP_MSG_GETBULK:
00461         snmp_log(LOG_DEBUG, "  GETBULK message, non-rep=%d, max_rep=%d\n",
00462                  pdu->errstat, pdu->errindex); break;
00463       case SNMP_MSG_INFORM:
00464         snmp_log(LOG_DEBUG, "  INFORM message\n"); break;
00465       case SNMP_MSG_TRAP2:
00466         snmp_log(LOG_DEBUG, "  TRAP2 message\n"); break;
00467       case SNMP_MSG_REPORT:
00468         snmp_log(LOG_DEBUG, "  REPORT message\n"); break;
00469       }
00470              
00471       for (var_ptr = pdu->variables; var_ptr != NULL;
00472            var_ptr=var_ptr->next_variable) {
00473         size_t c_oidlen = 256, c_outlen = 0;
00474         u_char *c_oid = (u_char *)malloc(c_oidlen);
00475 
00476         if (c_oid) {
00477           if (!sprint_realloc_objid(&c_oid, &c_oidlen, &c_outlen, 1,
00478                                     var_ptr->name, var_ptr->name_length)) {
00479             snmp_log(LOG_DEBUG, "    -- %s [TRUNCATED]\n", c_oid);
00480           } else {
00481             snmp_log(LOG_DEBUG, "    -- %s\n", c_oid);
00482           }
00483           free(c_oid);
00484         }
00485       }
00486     }
00487     return 1;
00488   }
00489   return 0; /* XXX: does it matter what the return value is?  Yes: if we
00490                return 0, then the PDU is dumped.  */
00491 }

int timeval_uptime struct timeval *    tv
 

Definition at line 1921 of file snmp_agent.c.

01922 {
01923     return marker_uptime((marker_t)tv);
01924 }

int wrap_up_request struct agent_snmp_session   asp,
int    status
 

Definition at line 874 of file snmp_agent.c.

Referenced by check_delayed_request(), and handle_snmp_packet().

00874                                                             {
00875     struct variable_list *var_ptr;
00876     int i;
00877 
00878     /* some stuff needs to be saved in special subagent cases */
00879     switch(asp->pdu->command) {
00880         case SNMP_MSG_INTERNAL_SET_BEGIN:
00881         case SNMP_MSG_INTERNAL_SET_RESERVE1:
00882         case SNMP_MSG_INTERNAL_SET_RESERVE2:
00883         case SNMP_MSG_INTERNAL_SET_ACTION:
00884         case SNMP_MSG_INTERNAL_SET_COMMIT:
00885         case SNMP_MSG_INTERNAL_SET_FREE:
00886         case SNMP_MSG_INTERNAL_SET_UNDO:
00887             save_set_cache(asp);
00888             break;
00889     }
00890     
00891     /*
00892      * May need to "dumb down" a SET error status for a
00893      * v1 query.  See RFC2576 - section 4.3
00894      */
00895     if (( asp->pdu                          ) &&
00896         ( asp->pdu->command == SNMP_MSG_SET ) &&
00897         ( asp->pdu->version == SNMP_VERSION_1 )) {
00898         switch ( status ) {
00899             case SNMP_ERR_WRONGVALUE:
00900             case SNMP_ERR_WRONGENCODING:
00901             case SNMP_ERR_WRONGTYPE:
00902             case SNMP_ERR_WRONGLENGTH:
00903             case SNMP_ERR_INCONSISTENTVALUE:
00904                 status = SNMP_ERR_BADVALUE;
00905                 break;
00906             case SNMP_ERR_NOACCESS:
00907             case SNMP_ERR_NOTWRITABLE:
00908             case SNMP_ERR_NOCREATION:
00909             case SNMP_ERR_INCONSISTENTNAME:
00910             case SNMP_ERR_AUTHORIZATIONERROR:
00911                 status = SNMP_ERR_NOSUCHNAME;
00912                 break;
00913             case SNMP_ERR_RESOURCEUNAVAILABLE:
00914             case SNMP_ERR_COMMITFAILED:
00915             case SNMP_ERR_UNDOFAILED:
00916                 status = SNMP_ERR_GENERR;
00917                 break;
00918         }
00919     }
00920     /*
00921      * Similarly we may need to "dumb down" v2 exception
00922      *  types to throw an error for a v1 query.
00923      *  See RFC2576 - section 4.1.2.3
00924      */
00925     if (( asp->pdu                          ) &&
00926         ( asp->pdu->command != SNMP_MSG_SET ) &&
00927         ( asp->pdu->version == SNMP_VERSION_1 )) {
00928         for ( var_ptr = asp->pdu->variables, i=1 ;
00929               var_ptr != NULL ;
00930               var_ptr = var_ptr->next_variable, i++ ) {
00931             switch ( var_ptr->type ) {
00932                 case SNMP_NOSUCHOBJECT:
00933                 case SNMP_NOSUCHINSTANCE:
00934                 case SNMP_ENDOFMIBVIEW:
00935                 case ASN_COUNTER64:
00936                     status = SNMP_ERR_NOSUCHNAME;
00937                     asp->index=i;
00938                     break;
00939             }
00940         }
00941     }
00942     if (( status == SNMP_ERR_NOERROR ) && ( asp->pdu )) {
00943         snmp_increment_statistic_by(
00944             (asp->pdu->command == SNMP_MSG_SET ?
00945              STAT_SNMPINTOTALSETVARS : STAT_SNMPINTOTALREQVARS ),
00946             count_varbinds( asp->pdu->variables ));
00947     }
00948     else {
00949         /*
00950          * Use a copy of the original request
00951          *   to report failures.
00952          */
00953         snmp_free_pdu( asp->pdu );
00954         asp->pdu = asp->orig_pdu;
00955         asp->orig_pdu = NULL;
00956     }
00957     if ( asp->pdu ) {
00958         asp->pdu->command  = SNMP_MSG_RESPONSE;
00959         asp->pdu->errstat  = asp->status;
00960         asp->pdu->errindex = asp->index;
00961         if (! snmp_send( asp->session, asp->pdu ))
00962             snmp_free_pdu(asp->pdu);
00963         snmp_increment_statistic(STAT_SNMPOUTPKTS);
00964         snmp_increment_statistic(STAT_SNMPOUTGETRESPONSES);
00965         asp->pdu = NULL;
00966         remove_and_free_agent_snmp_session(asp);
00967     }
00968     return 1;
00969 }

Variable Documentation

struct agent_snmp_session* agent_delegated_list = NULL
 

Definition at line 136 of file snmp_agent.c.

int lastAddrAge = 0
 

Definition at line 122 of file snmp_agent.c.

int log_addresses = 0
 

Definition at line 123 of file snmp_agent.c.

struct snmp_session* main_session = NULL
 

Definition at line 500 of file snmp_agent.c.

struct timeval starttime
 

Definition at line 1907 of file snmp_agent.c.


Generated on Sat Nov 10 14:09:56 2001 for net-snmp by doxygen1.2.11 written by Dimitri van Heesch, © 1997-2001
[an error occurred while processing this directive] [an error occurred while processing this directive]

Valid CSS!


Last modified: Wednesday, 01-Aug-2018 04:41:28 UTC
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.