From: wessels <> Date: Fri, 21 Nov 1997 08:58:57 +0000 (+0000) Subject: gindent X-Git-Tag: SQUID_3_0_PRE1~4500 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=da2d50d1b7f6df01b5276ca63e22f9c35cd65774;p=thirdparty%2Fsquid.git gindent --- diff --git a/include/asn1.h b/include/asn1.h index 979c39b3ae..8fd4456866 100644 --- a/include/asn1.h +++ b/include/asn1.h @@ -32,18 +32,18 @@ SOFTWARE. #undef _ANSI_ARGS_ #if (defined(__STDC__) && ! defined(NO_PROTOTYPE)) || defined(USE_PROTOTYPE) -# define _ANSI_ARGS_(x) x +#define _ANSI_ARGS_(x) x #else -# define _ANSI_ARGS_(x) () +#define _ANSI_ARGS_(x) () #endif #include #ifndef EIGHTBIT_SUBIDS -typedef u_long oid; +typedef u_long oid; #define MAX_SUBID 0xFFFFFFFF #else -typedef u_char oid; +typedef u_char oid; #define MAX_SUBID 0xFF #endif @@ -92,108 +92,108 @@ typedef long int32; struct counter64 { u_int32 high; u_int32 low; - }; - - -extern u_char *asn_parse_int _ANSI_ARGS_((u_char *data, - int *datalength, - u_char *type, - long *intp, - int intsize)); - -extern u_char *asn_build_int _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - long *intp, - int intsize)); - -extern u_char *asn_parse_unsigned_int _ANSI_ARGS_((u_char *data, - int *datalength, - u_char *type, - u_long *intp, - int intsize)); - -extern u_char *asn_build_unsigned_int _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - u_long *intp, - int intsize)); - -extern u_char *asn_parse_string _ANSI_ARGS_((u_char *data, - int *datalength, - u_char *type, - u_char *string, - int *len)); - -extern u_char *asn_build_string _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - u_char *str, - int len)); - -extern u_char *asn_parse_header _ANSI_ARGS_((u_char *data, - int *datalength, - u_char *type)); - -extern u_char *asn_build_header _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - int len)); - -extern u_char *asn_build_sequence _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - int len)); - -extern u_char *asn_parse_length _ANSI_ARGS_((u_char *data, - u_long *eln)); - -extern u_char *asn_build_length _ANSI_ARGS_((u_char *data, - int *datalength, - int len)); - -extern u_char *asn_parse_objid _ANSI_ARGS_(( - u_char *data, - int *datalength, - u_char *type, - oid *objid, - int *objidlength)); - -extern u_char *asn_build_objid _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - oid *objid, - int objidlength)); - -extern u_char *asn_parse_null _ANSI_ARGS_((u_char *data, - int *datalength, - u_char *type)); - -extern u_char *asn_build_null _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type)); -extern u_char *asn_parse_bitstring _ANSI_ARGS_((u_char *data, - int *datalength, - u_char *type, - u_char *str, - int *len)); - -extern u_char *asn_build_bitstring _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - u_char *str, - int len)); - -extern u_char *asn_parse_unsigned_int64 _ANSI_ARGS_((u_char *data, - int *datalength, - u_char *type, - struct counter64 *cp, - int cp_size)); - -extern u_char *asn_build_unsigned_int64 _ANSI_ARGS_((u_char *data, - int *datalength, - u_char type, - struct counter64 *cp, - int cp_size)); +}; + + +extern u_char *asn_parse_int _ANSI_ARGS_((u_char * data, + int *datalength, + u_char * type, + long *intp, + int intsize)); + +extern u_char *asn_build_int _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + long *intp, + int intsize)); + +extern u_char *asn_parse_unsigned_int _ANSI_ARGS_((u_char * data, + int *datalength, + u_char * type, + u_long * intp, + int intsize)); + +extern u_char *asn_build_unsigned_int _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + u_long * intp, + int intsize)); + +extern u_char *asn_parse_string _ANSI_ARGS_((u_char * data, + int *datalength, + u_char * type, + u_char * string, + int *len)); + +extern u_char *asn_build_string _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + u_char * str, + int len)); + +extern u_char *asn_parse_header _ANSI_ARGS_((u_char * data, + int *datalength, + u_char * type)); + +extern u_char *asn_build_header _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + int len)); + +extern u_char *asn_build_sequence _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + int len)); + +extern u_char *asn_parse_length _ANSI_ARGS_((u_char * data, + u_long * eln)); + +extern u_char *asn_build_length _ANSI_ARGS_((u_char * data, + int *datalength, + int len)); + +extern u_char *asn_parse_objid _ANSI_ARGS_(( + u_char * data, + int *datalength, + u_char * type, + oid * objid, + int *objidlength)); + +extern u_char *asn_build_objid _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + oid * objid, + int objidlength)); + +extern u_char *asn_parse_null _ANSI_ARGS_((u_char * data, + int *datalength, + u_char * type)); + +extern u_char *asn_build_null _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type)); +extern u_char *asn_parse_bitstring _ANSI_ARGS_((u_char * data, + int *datalength, + u_char * type, + u_char * str, + int *len)); + +extern u_char *asn_build_bitstring _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + u_char * str, + int len)); + +extern u_char *asn_parse_unsigned_int64 _ANSI_ARGS_((u_char * data, + int *datalength, + u_char * type, + struct counter64 * cp, + int cp_size)); + +extern u_char *asn_build_unsigned_int64 _ANSI_ARGS_((u_char * data, + int *datalength, + u_char type, + struct counter64 * cp, + int cp_size)); #endif diff --git a/include/md5.h b/include/md5.h index 37d1d34539..7e71b5d78c 100644 --- a/include/md5.h +++ b/include/md5.h @@ -4,9 +4,9 @@ */ /* PROTOTYPES should be set to one if and only if the compiler supports - function argument prototyping. -The following makes PROTOTYPES default to 0 if it has not already - been defined with C compiler flags. + * function argument prototyping. + * The following makes PROTOTYPES default to 0 if it has not already + * been defined with C compiler flags. */ #ifndef PROTOTYPES #define PROTOTYPES 0 @@ -22,8 +22,8 @@ typedef unsigned short int UINT2; typedef unsigned long int UINT4; /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. -If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it - returns an empty list. + * If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it + * returns an empty list. */ #if PROTOTYPES #define PROTO_LIST(list) list @@ -35,36 +35,35 @@ If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it */ /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All -rights reserved. - -License to copy and use this software is granted provided that it -is identified as the "RSA Data Security, Inc. MD5 Message-Digest -Algorithm" in all material mentioning or referencing this software -or this function. - -License is also granted to make and use derivative works provided -that such works are identified as "derived from the RSA Data -Security, Inc. MD5 Message-Digest Algorithm" in all material -mentioning or referencing the derived work. - -RSA Data Security, Inc. makes no representations concerning either -the merchantability of this software or the suitability of this -software for any particular purpose. It is provided "as is" -without express or implied warranty of any kind. - -These notices must be retained in any copies of any part of this -documentation and/or software. + * rights reserved. + * + * License to copy and use this software is granted provided that it + * is identified as the "RSA Data Security, Inc. MD5 Message-Digest + * Algorithm" in all material mentioning or referencing this software + * or this function. + * + * License is also granted to make and use derivative works provided + * that such works are identified as "derived from the RSA Data + * Security, Inc. MD5 Message-Digest Algorithm" in all material + * mentioning or referencing the derived work. + * + * RSA Data Security, Inc. makes no representations concerning either + * the merchantability of this software or the suitability of this + * software for any particular purpose. It is provided "as is" + * without express or implied warranty of any kind. + * + * These notices must be retained in any copies of any part of this + * documentation and/or software. */ /* MD5 context. */ typedef struct { - UINT4 state[4]; /* state (ABCD) */ - UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ - unsigned char buffer[64]; /* input buffer */ + UINT4 state[4]; /* state (ABCD) */ + UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + unsigned char buffer[64]; /* input buffer */ } MD5_CTX; -void MD5Init PROTO_LIST ((MD5_CTX *)); +void MD5Init PROTO_LIST((MD5_CTX *)); void MD5Update PROTO_LIST - ((MD5_CTX *, unsigned char *, unsigned int)); -void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); - + ((MD5_CTX *, unsigned char *, unsigned int)); +void MD5Final PROTO_LIST((unsigned char[16], MD5_CTX *)); diff --git a/include/parse.h b/include/parse.h index 67a251260e..4343e75576 100644 --- a/include/parse.h +++ b/include/parse.h @@ -30,9 +30,9 @@ SOFTWARE. #undef _ANSI_ARGS_ #if (defined(__STDC__) && ! defined(NO_PROTOTYPE)) || defined(USE_PROTOTYPE) -# define _ANSI_ARGS_(x) x +#define _ANSI_ARGS_(x) x #else -# define _ANSI_ARGS_(x) () +#define _ANSI_ARGS_(x) () #endif @@ -47,7 +47,7 @@ SOFTWARE. */ struct enum_list { struct enum_list *next; - int value; + int value; char *label; }; @@ -56,13 +56,13 @@ struct enum_list { */ struct node { struct node *next; - char label[MAXLABEL]; /* This node's (unique) textual name */ - u_long subid; /* This node's integer subidentifier */ - char parent[MAXLABEL];/* The parent's textual name */ - int type; /* The type of object this represents */ + char label[MAXLABEL]; /* This node's (unique) textual name */ + u_long subid; /* This node's integer subidentifier */ + char parent[MAXLABEL]; /* The parent's textual name */ + int type; /* The type of object this represents */ struct enum_list *enums; /* (optional) list of enumerated integers -(otherwise NULL) */ - char *description; /* description (a quoted string) */ + * (otherwise NULL) */ + char *description; /* description (a quoted string) */ }; /* @@ -72,13 +72,13 @@ struct tree { struct tree *child_list; /* list of children of this node */ struct tree *next_peer; /* Next node in list of peers */ struct tree *parent; - char label[MAXLABEL]; /* This node's textual name */ + char label[MAXLABEL]; /* This node's textual name */ u_long subid; /* This node's integer subidentifier */ int type; /* This node's object type */ struct enum_list *enums; /* (optional) list of enumerated integers -(otherwise NULL) */ - void (*printer)(); /* Value printing function */ - char *description; /* description (a quoted string) */ + * (otherwise NULL) */ + void (*printer) (); /* Value printing function */ + char *description; /* description (a quoted string) */ }; /* non-aggregate types for tree end nodes */ diff --git a/include/snmp.h b/include/snmp.h index d3b47c38ea..fc43bd618b 100644 --- a/include/snmp.h +++ b/include/snmp.h @@ -113,35 +113,35 @@ SOFTWARE. typedef struct _conf_if_list { - char *name; - int type; - int speed; - struct _conf_if_list *next; + char *name; + int type; + int speed; + struct _conf_if_list *next; } conf_if_list; extern conf_if_list *if_list; #ifndef SQUID_SNMP -/*extern void init_snmp();*/ - -extern int read_objid (char *input, - oid *output, - int *out_len); - -extern void sprint_objid (char *buf,oid *id,int idlen); -extern void print_objid (oid *id, - int idlen); -void snmp_add_null_var (struct snmp_pdu *, - oid *, - int); -extern void xdump (u_char *cp, - int length, - char *prefix); - -extern void snmp_synch_setup (struct snmp_session *session); - -extern int snmp_synch_response (struct snmp_session *ss, - struct snmp_pdu *pdu, - struct snmp_pdu **response); +/*extern void init_snmp(); */ + +extern int read_objid(char *input, + oid * output, + int *out_len); + +extern void sprint_objid(char *buf, oid * id, int idlen); +extern void print_objid(oid * id, + int idlen); +void snmp_add_null_var(struct snmp_pdu *, + oid *, + int); +extern void xdump(u_char * cp, + int length, + char *prefix); + +extern void snmp_synch_setup(struct snmp_session *session); + +extern int snmp_synch_response(struct snmp_session *ss, + struct snmp_pdu *pdu, + struct snmp_pdu **response); #endif #endif diff --git a/include/snmp_api.h b/include/snmp_api.h index 336aa5cf6b..c8bbbd8ca8 100644 --- a/include/snmp_api.h +++ b/include/snmp_api.h @@ -30,9 +30,9 @@ SOFTWARE. #undef _ANSI_ARGS_ #if (defined(__STDC__) && ! defined(NO_PROTOTYPE)) || defined(USE_PROTOTYPE) -# define _ANSI_ARGS_(x) x +#define _ANSI_ARGS_(x) x #else -# define _ANSI_ARGS_(x) () +#define _ANSI_ARGS_(x) () #endif @@ -50,62 +50,62 @@ typedef int ssize_t; typedef struct sockaddr_in ipaddr; typedef struct { - u_char securityModel; - u_char qoS; - u_char agentID[12]; - u_long agentBoots; - int agentTime; - int MMS; - int userLen; - u_char userName[16]; - int authLen; - u_char authDigest[16]; - u_char *authDigestPtr; - int contextLen; - u_char contextSelector[40]; + u_char securityModel; + u_char qoS; + u_char agentID[12]; + u_long agentBoots; + int agentTime; + int MMS; + int userLen; + u_char userName[16]; + int authLen; + u_char authDigest[16]; + u_char *authDigestPtr; + int contextLen; + u_char contextSelector[40]; } Parameters; struct snmp_session { - int retries; /* Number of retries before timeout. */ - long timeout; /* Number of uS until first timeout, then exponential backoff */ - char *peername; /* Domain name or dotted IP address of default peer */ + int retries; /* Number of retries before timeout. */ + long timeout; /* Number of uS until first timeout, then exponential backoff */ + char *peername; /* Domain name or dotted IP address of default peer */ u_short remote_port; /* UDP port number of peer. */ - u_short local_port; /* My UDP port number, 0 for default, picked randomly */ + u_short local_port; /* My UDP port number, 0 for default, picked randomly */ /* Authentication function or NULL if null authentication is used */ - int (*authenticator)(); - int (*callback)(); /* Function to interpret incoming data */ + int (*authenticator) (); + int (*callback) (); /* Function to interpret incoming data */ /* Pointer to data that the callback function may consider important */ - void *callback_magic; + void *callback_magic; - int version; /* SNMP version number */ + int version; /* SNMP version number */ /* fields to support SNMPv1 community model */ - int community_len; - u_char *community; + int community_len; + u_char *community; /* the private keys to use for user-based security */ - u_char authKey[16]; - u_char privKey[16]; + u_char authKey[16]; + u_char privKey[16]; /* fields to support user-based security model in SNMPv2 */ - Parameters params; - - u_char qoS; - u_char agentID[16]; - u_long agentBoots; - int agentTime; /* the agentTime value */ - int agentClock; /* the running agentClock */ - int userLen; - u_char userName[32]; - int MMS; - int contextLen; - u_char contextSelector[64]; + Parameters params; + + u_char qoS; + u_char agentID[16]; + u_long agentBoots; + int agentTime; /* the agentTime value */ + int agentClock; /* the running agentClock */ + int userLen; + u_char userName[32]; + int MMS; + int contextLen; + u_char contextSelector[64]; /* misc stuff */ - int readView; - int writeView; + int readView; + int writeView; }; /* @@ -134,55 +134,55 @@ struct snmp_session { extern int snmp_errno; /* Error return values */ #define SNMPERR_GENERR -1 -#define SNMPERR_BAD_LOCPORT -2 /* local port was already in use */ +#define SNMPERR_BAD_LOCPORT -2 /* local port was already in use */ #define SNMPERR_BAD_ADDRESS -3 #define SNMPERR_BAD_SESSION -4 #define SNMPERR_TOO_LONG -5 struct snmp_pdu { - ipaddr address; /* Address of peer */ + ipaddr address; /* Address of peer */ - int command; /* Type of this PDU */ + int command; /* Type of this PDU */ Parameters params; - u_long reqid; /* Request id */ - u_long errstat; /* Error status */ - u_long errindex; /* Error index */ + u_long reqid; /* Request id */ + u_long errstat; /* Error status */ + u_long errindex; /* Error index */ /* Trap information */ - oid *enterprise;/* System OID */ - int enterprise_length; - ipaddr agent_addr; /* address of object generating trap */ - int trap_type; /* trap type */ - int specific_type; /* specific type */ - u_long time; /* Uptime */ + oid *enterprise; /* System OID */ + int enterprise_length; + ipaddr agent_addr; /* address of object generating trap */ + int trap_type; /* trap type */ + int specific_type; /* specific type */ + u_long time; /* Uptime */ struct variable_list *variables; }; struct variable_list { - struct variable_list *next_variable; /* NULL for last variable */ - oid *name; /* Object identifier of variable */ - int name_length; /* number of subid's in name */ - u_char type; /* ASN type of variable */ - union { /* value of variable */ - long *integer; - u_char *string; - oid *objid; - u_char *bitstring; + struct variable_list *next_variable; /* NULL for last variable */ + oid *name; /* Object identifier of variable */ + int name_length; /* number of subid's in name */ + u_char type; /* ASN type of variable */ + union { /* value of variable */ + long *integer; + u_char *string; + oid *objid; + u_char *bitstring; struct counter64 *counter64; } val; - int val_len; + int val_len; }; #ifndef SQUID_SNMP /* * struct snmp_session *snmp_open(session) - * struct snmp_session *session; + * struct snmp_session *session; * * Sets up the session with the snmp_session information provided * by the user. Then opens and binds the necessary UDP port. @@ -190,7 +190,7 @@ struct variable_list { * the pointer passed to snmp_open()). On any error, NULL is returned * and snmp_errno is set to the appropriate error code. */ -struct snmp_session *snmp_open _ANSI_ARGS_((struct snmp_session *session)); +struct snmp_session *snmp_open _ANSI_ARGS_((struct snmp_session * session)); /* * int snmp_close(session) @@ -200,13 +200,13 @@ struct snmp_session *snmp_open _ANSI_ARGS_((struct snmp_session *session)); * dequeues any pending requests, and closes any sockets allocated for * the session. Returns 0 on error, 1 otherwise. */ -int snmp_close _ANSI_ARGS_((struct snmp_session *session)); +int snmp_close _ANSI_ARGS_((struct snmp_session * session)); /* * int snmp_send(session, pdu) * struct snmp_session *session; - * struct snmp_pdu *pdu; + * struct snmp_pdu *pdu; * * Sends the input pdu on the session after calling snmp_build to create * a serialized packet. If necessary, set some of the pdu data from the @@ -216,8 +216,8 @@ int snmp_close _ANSI_ARGS_((struct snmp_session *session)); * On any error, 0 is returned. * The pdu is freed by snmp_send() unless a failure occured. */ -int snmp_send _ANSI_ARGS_((struct snmp_session *session, - struct snmp_pdu *pdu)); +int snmp_send _ANSI_ARGS_((struct snmp_session * session, + struct snmp_pdu * pdu)); /* @@ -230,7 +230,7 @@ int snmp_send _ANSI_ARGS_((struct snmp_session *session, * is passed to the callback routine for that session. If the callback * routine returns successfully, the pdu and it's request are deleted. */ -void snmp_read (fd_set *fdset); +void snmp_read(fd_set * fdset); /* @@ -240,7 +240,7 @@ void snmp_read (fd_set *fdset); * * Frees the pdu and any malloc'd data associated with it. */ -void snmp_free_pdu (struct snmp_pdu *pdu); +void snmp_free_pdu(struct snmp_pdu *pdu); /* * int snmp_select_info(numfds, fdset, timeout, block) @@ -269,9 +269,9 @@ void snmp_free_pdu (struct snmp_pdu *pdu); * snmp_select_info returns the number of open sockets. (i.e. The number of sessions open) */ int snmp_select_info _ANSI_ARGS_((int *numfds, - fd_set *fdset, - struct timeval *timeout, - int *block)); + fd_set * fdset, + struct timeval * timeout, + int *block)); /* * void snmp_timeout(); @@ -291,10 +291,10 @@ void snmp_timeout _ANSI_ARGS_((void)); * This routine must be supplied by the application: * * u_char *authenticator(pdu, length, community, community_len) - * u_char *pdu; The rest of the PDU to be authenticated - * int *length; The length of the PDU (updated by the authenticator) - * u_char *community; The community name to authenticate under. - * int community_len The length of the community name. + * u_char *pdu; The rest of the PDU to be authenticated + * int *length; The length of the PDU (updated by the authenticator) + * u_char *community; The community name to authenticate under. + * int community_len The length of the community name. * * Returns the authenticated pdu, or NULL if authentication failed. * If null authentication is used, the authenticator in snmp_session can be @@ -307,9 +307,9 @@ void snmp_timeout _ANSI_ARGS_((void)); * int callback(operation, session, reqid, pdu, magic) * int operation; * struct snmp_session *session; The session authenticated under. - * int reqid; The request id of this pdu (0 for TRAP) - * struct snmp_pdu *pdu; The pdu information. - * void *magic A link to the data for this routine. + * int reqid; The request id of this pdu (0 for TRAP) + * struct snmp_pdu *pdu; The pdu information. + * void *magic A link to the data for this routine. * * Returns 1 if request was successful, 0 if it should be kept pending. * Any data in the pdu must be copied because it will be freed elsewhere. diff --git a/include/snmp_client.h b/include/snmp_client.h index b1b9249e23..6517520bef 100644 --- a/include/snmp_client.h +++ b/include/snmp_client.h @@ -29,15 +29,15 @@ SOFTWARE. #undef _ANSI_ARGS_ #if (defined(__STDC__) && ! defined(NO_PROTOTYPE)) || defined(USE_PROTOTYPE) -# define _ANSI_ARGS_(x) x +#define _ANSI_ARGS_(x) x #else -# define _ANSI_ARGS_(x) () +#define _ANSI_ARGS_(x) () #endif struct synch_state { - int waiting; + int waiting; int status; /* status codes */ #define STAT_SUCCESS 0 @@ -51,8 +51,8 @@ extern struct synch_state snmp_synch_state; extern struct snmp_pdu *snmp_pdu_create _ANSI_ARGS_((int cmd)); -extern struct snmp_pdu *snmp_fix_pdu _ANSI_ARGS_((struct snmp_pdu *pdu, - int cmd)); +extern struct snmp_pdu *snmp_fix_pdu _ANSI_ARGS_((struct snmp_pdu * pdu, + int cmd)); extern char *snmp_errstring _ANSI_ARGS_((int errstat)); #endif diff --git a/include/snmp_impl.h b/include/snmp_impl.h index 46a96c7d2e..22205dbc0a 100644 --- a/include/snmp_impl.h +++ b/include/snmp_impl.h @@ -31,9 +31,9 @@ SOFTWARE. #undef _ANSI_ARGS_ #if (defined(__STDC__) && ! defined(NO_PROTOTYPE)) || defined(USE_PROTOTYPE) -# define _ANSI_ARGS_(x) x +#define _ANSI_ARGS_(x) x #else -# define _ANSI_ARGS_(x) () +#define _ANSI_ARGS_(x) () #endif @@ -55,7 +55,7 @@ SOFTWARE. #define BUILD_ERROR -2 #define SID_MAX_LEN 200 -#define MAX_NAME_LEN 64 /* number of subid's in a objid */ +#define MAX_NAME_LEN 64 /* number of subid's in a objid */ #ifndef NULL #define NULL 0 @@ -77,9 +77,9 @@ SOFTWARE. #define ACTION 3 #define FREE 4 -#define RONLY 0xAAAA /* read access for everyone */ -#define RWRITE 0xAABA /* add write access for community private */ -#define NOACCESS 0x0000 /* no access for anybody */ +#define RONLY 0xAAAA /* read access for everyone */ +#define RWRITE 0xAABA /* add write access for community private */ +#define NOACCESS 0x0000 /* no access for anybody */ #define INTEGER ASN_INTEGER #define STRING ASN_OCTET_STR @@ -103,35 +103,35 @@ SOFTWARE. #define ERROR(string) #endif -/* from snmp.c*/ -extern u_char sid[]; /* size SID_MAX_LEN */ - -extern u_char *snmp_parse_var_op _ANSI_ARGS_((u_char *data, - oid *var_name, - int *var_name_len, - u_char *var_val_type, - int *var_val_len, - u_char **var_val, - int *listlength)); - -extern u_char *snmp_build_var_op _ANSI_ARGS_((u_char *data, - oid *var_name, - int *var_name_len, - u_char var_val_type, - int var_val_len, - u_char *var_val, - int *listlength)); - -extern u_char *snmp_auth_parse _ANSI_ARGS_((u_char *data, - int *length, - u_char *sid, - int *slen, - long *version)); - -extern u_char *snmp_auth_build _ANSI_ARGS_((u_char *data, - int *length, - struct snmp_session *session, - int is_agent, - int messagelen)); +/* from snmp.c */ +extern u_char sid[]; /* size SID_MAX_LEN */ + +extern u_char *snmp_parse_var_op _ANSI_ARGS_((u_char * data, + oid * var_name, + int *var_name_len, + u_char * var_val_type, + int *var_val_len, + u_char ** var_val, + int *listlength)); + +extern u_char *snmp_build_var_op _ANSI_ARGS_((u_char * data, + oid * var_name, + int *var_name_len, + u_char var_val_type, + int var_val_len, + u_char * var_val, + int *listlength)); + +extern u_char *snmp_auth_parse _ANSI_ARGS_((u_char * data, + int *length, + u_char * sid, + int *slen, + long *version)); + +extern u_char *snmp_auth_build _ANSI_ARGS_((u_char * data, + int *length, + struct snmp_session * session, + int is_agent, + int messagelen)); #endif diff --git a/include/snmp_util.h b/include/snmp_util.h index d9be9146ff..2b927fd22f 100644 --- a/include/snmp_util.h +++ b/include/snmp_util.h @@ -4,9 +4,9 @@ #undef _ANSI_ARGS_ #if (defined(__STDC__) && ! defined(NO_PROTOTYPE)) || defined(USE_PROTOTYPE) -# define _ANSI_ARGS_(x) x +#define _ANSI_ARGS_(x) x #else -# define _ANSI_ARGS_(x) () +#define _ANSI_ARGS_(x) () #endif @@ -20,55 +20,55 @@ extern void snmp_alarm _ANSI_ARGS_((int ival, void (*handler) (void))); * service for filedescriptors: */ -extern void fd_add _ANSI_ARGS_((int fd, void (*func)(int fd))); +extern void fd_add _ANSI_ARGS_((int fd, void (*func) (int fd))); extern void fd_service _ANSI_ARGS_((void)); /* ---------------------------------------------------------------------- */ /* -** SNMP Agent extension for Spacer-Controler Management -** -** Copyright (c) 1997 FT/CNET/DES/GRL Olivier Montanuy -** -*/ + * ** SNMP Agent extension for Spacer-Controler Management + * ** + * ** Copyright (c) 1997 FT/CNET/DES/GRL Olivier Montanuy + * ** + */ /* -** Function to safely copy a string, and ensure the last -** character is always '\0'. -*/ + * ** Function to safely copy a string, and ensure the last + * ** character is always '\0'. + */ void strcpy_safe _ANSI_ARGS_((char *str, int str_len, char *val)); /* -** Function to get IP address of this agent -** WARNING: this scans all interfaces (slow) -*/ -u_long + * ** Function to get IP address of this agent + * ** WARNING: this scans all interfaces (slow) + */ +u_long Util_local_ip_address _ANSI_ARGS_((void)); /* -** Function to get the current time in seconds -*/ -long + * ** Function to get the current time in seconds + */ +long Util_time_now _ANSI_ARGS_((void)); /* -** Function to determine how long the agent has been running -* (WARNING: this seems rather slow) -*/ -long -Util_time_running(); + * ** Function to determine how long the agent has been running + * * (WARNING: this seems rather slow) + */ +long + Util_time_running(); /* -** Read data from file -*/ + * ** Read data from file + */ int Util_file_read _ANSI_ARGS_((char *file, int offset, char *data, int dataSz)); /* -** Write data into file -*/ + * ** Write data into file + */ int Util_file_write _ANSI_ARGS_((char *file, int offset, char *data, int dataSz)); diff --git a/include/snmp_vars.h b/include/snmp_vars.h index 9a468907ca..7ff8e55fcb 100644 --- a/include/snmp_vars.h +++ b/include/snmp_vars.h @@ -31,35 +31,35 @@ PERFORMANCE OF THIS SOFTWARE. #undef _ANSI_ARGS_ #if (defined(__STDC__) && ! defined(NO_PROTOTYPE)) || defined(USE_PROTOTYPE) -# define _ANSI_ARGS_(x) x +#define _ANSI_ARGS_(x) x #else -# define _ANSI_ARGS_(x) () +#define _ANSI_ARGS_(x) () #endif -u_char *var_system(); -u_char *var_ifEntry(); -u_char *var_atEntry(); -u_char *var_ip(); -u_char *var_ipAddrEntry(); -u_char *var_ipRouteEntry(); -u_char *var_icmp(); -u_char *var_tcp(); -u_char *var_udp(); +u_char *var_system(); +u_char *var_ifEntry(); +u_char *var_atEntry(); +u_char *var_ip(); +u_char *var_ipAddrEntry(); +u_char *var_ipRouteEntry(); +u_char *var_icmp(); +u_char *var_tcp(); +u_char *var_udp(); #ifdef linux -u_char *var_snmp(); -u_char *var_id(); +u_char *var_snmp(); +u_char *var_id(); #endif -u_char *var_process(); -u_char *var_event(); -u_char *var_capture(); -u_char *var_demo(); -u_char *var_snmpStats(); -u_char *var_usecStats(); -u_char *var_usecAgent(); -u_char *var_orEntry(); -u_char *var_rwstats(); -u_char *getStatPtr(); +u_char *var_process(); +u_char *var_event(); +u_char *var_capture(); +u_char *var_demo(); +u_char *var_snmpStats(); +u_char *var_usecStats(); +u_char *var_usecAgent(); +u_char *var_orEntry(); +u_char *var_rwstats(); +u_char *getStatPtr(); extern long long_return; extern u_char return_buf[]; @@ -257,32 +257,33 @@ extern u_char return_buf[]; #ifdef linux struct inpcb { - struct inpcb *inp_next; /* pointers to other pcb's */ - struct in_addr inp_faddr; /* foreign host table entry */ - u_short inp_fport; /* foreign port */ - struct in_addr inp_laddr; /* local host table entry */ - u_short inp_lport; /* local port */ - int inp_state; - int uid; /* owner of the connection */ + struct inpcb *inp_next; /* pointers to other pcb's */ + struct in_addr inp_faddr; /* foreign host table entry */ + u_short inp_fport; /* foreign port */ + struct in_addr inp_laddr; /* local host table entry */ + u_short inp_lport; /* local port */ + int inp_state; + int uid; /* owner of the connection */ }; + #endif -extern void TCP_Scan_Init (); -extern int TCP_Scan_Next (); +extern void TCP_Scan_Init(); +extern int TCP_Scan_Next(); struct variable { - u_char magic; /* passed to function as a hint */ - char type; /* type of variable */ + u_char magic; /* passed to function as a hint */ + char type; /* type of variable */ /* See important comment in snmp_vars.c relating to acl */ - u_short acl; /* access control list for variable */ - u_char *(*findVar)(); /* function that finds variable */ - u_char namelen; /* length of above */ - oid name[32]; /* object identifier of variable */ + u_short acl; /* access control list for variable */ + u_char *(*findVar) (); /* function that finds variable */ + u_char namelen; /* length of above */ + oid name[32]; /* object identifier of variable */ }; -extern int compare (); -extern void Interface_Scan_Init (); -extern int Interface_Scan_Next (); +extern int compare(); +extern void Interface_Scan_Init(); +extern int Interface_Scan_Next(); #endif diff --git a/include/splay.h b/include/splay.h index f1d22fa2d1..460aa10b08 100644 --- a/include/splay.h +++ b/include/splay.h @@ -5,10 +5,10 @@ typedef struct _splay_node { struct _splay_node *right; } splayNode; -typedef int SPCMP (const void *, splayNode *); +typedef int SPCMP(const void *, splayNode *); extern int splayLastResult; splayNode *splay_insert(void *, splayNode *, SPCMP *); -splayNode *splay_splay(const void *, splayNode *, SPCMP* ); +splayNode *splay_splay(const void *, splayNode *, SPCMP *); void splay_destroy(splayNode *, void (*)(void *)); diff --git a/lib/snprintf.c b/lib/snprintf.c index 75bbbd1629..5f3be08af6 100644 --- a/lib/snprintf.c +++ b/lib/snprintf.c @@ -1,3 +1,4 @@ + /* ==================================================================== * Copyright (c) 1995-1997 The Apache Group. All rights reserved. * diff --git a/lib/splay.c b/lib/splay.c index 72b439950a..5fca86d90f 100644 --- a/lib/splay.c +++ b/lib/splay.c @@ -17,7 +17,7 @@ int splayLastResult = 0; splayNode * -splay_insert(void *data, splayNode * top, SPCMP *compare) +splay_insert(void *data, splayNode * top, SPCMP * compare) { splayNode *new = xcalloc(sizeof(splayNode), 1); new->data = data; @@ -44,7 +44,7 @@ splay_insert(void *data, splayNode * top, SPCMP *compare) } splayNode * -splay_splay(const void *data, splayNode * top, SPCMP *compare) +splay_splay(const void *data, splayNode * top, SPCMP * compare) { splayNode N; splayNode *l; diff --git a/snmplib/asn1.c b/snmplib/asn1.c index 55d60721e1..cb520f104f 100644 --- a/snmplib/asn1.c +++ b/snmplib/asn1.c @@ -71,41 +71,41 @@ SOFTWARE. */ u_char * asn_parse_int(data, datalength, type, intp, intsize) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - asn type of object */ - long *intp; /* IN/OUT - pointer to start of output buffer */ - int intsize; /* IN - size of output buffer */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - asn type of object */ + long *intp; /* IN/OUT - pointer to start of output buffer */ + int intsize; /* IN - size of output buffer */ { /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* */ u_char *bufp = data; - u_long asn_length; - long value = 0; + u_long asn_length; + long value = 0; - if (intsize != sizeof (long)){ + if (intsize != sizeof(long)) { ERROR("not long"); return NULL; } *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); - if (bufp == NULL){ + if (bufp == NULL) { ERROR("bad length"); return NULL; } - if (asn_length + (bufp - data) > *datalength){ + if (asn_length + (bufp - data) > *datalength) { ERROR("overflow of message"); return NULL; } - if (asn_length > intsize){ + if (asn_length > intsize) { ERROR("I don't support such large integers"); return NULL; } - *datalength -= (int)asn_length + (bufp - data); + *datalength -= (int) asn_length + (bufp - data); if (*bufp & 0x80) - value = -1; /* integer is negative */ - while(asn_length--) + value = -1; /* integer is negative */ + while (asn_length--) value = (value << 8) | *bufp++; *intp = value; return bufp; @@ -124,42 +124,42 @@ asn_parse_int(data, datalength, type, intp, intsize) */ u_char * asn_parse_unsigned_int(data, datalength, type, intp, intsize) - u_char *data; /* IN - pointer to start of object */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - asn type of object */ - u_long *intp; /* IN/OUT - pointer to start of output buffer */ - int intsize; /* IN - size of output buffer */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - asn type of object */ + u_long *intp; /* IN/OUT - pointer to start of output buffer */ + int intsize; /* IN - size of output buffer */ { /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* */ u_char *bufp = data; - u_long asn_length; + u_long asn_length; u_long value = 0; - if (intsize != sizeof (long)){ + if (intsize != sizeof(long)) { ERROR("not long"); return NULL; } *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); - if (bufp == NULL){ + if (bufp == NULL) { ERROR("bad length"); return NULL; } - if (asn_length + (bufp - data) > *datalength){ + if (asn_length + (bufp - data) > *datalength) { ERROR("overflow of message"); return NULL; } if ((asn_length > (intsize + 1)) || - ((asn_length == intsize + 1) && *bufp != 0x00)){ + ((asn_length == intsize + 1) && *bufp != 0x00)) { ERROR("I don't support such large integers"); return NULL; } - *datalength -= (int)asn_length + (bufp - data); + *datalength -= (int) asn_length + (bufp - data); if (*bufp & 0x80) - value = -1; /* integer is negative */ - while(asn_length--) + value = -1; /* integer is negative */ + while (asn_length--) value = (value << 8) | *bufp++; *intp = value; return bufp; @@ -178,11 +178,11 @@ asn_parse_unsigned_int(data, datalength, type, intp, intsize) */ u_char * asn_build_int(data, datalength, type, intp, intsize) - u_char *data; /* IN - pointer to start of output buffer */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - asn type of object */ - long *intp; /* IN - pointer to start of long integer */ - int intsize; /* IN - size of *intp */ + u_char *data; /* IN - pointer to start of output buffer */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - asn type of object */ + long *intp; /* IN - pointer to start of long integer */ + int intsize; /* IN - size of *intp */ { /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* @@ -191,7 +191,7 @@ asn_build_int(data, datalength, type, intp, intsize) long integer; u_long mask; - if (intsize != sizeof (long)) { + if (intsize != sizeof(long)) { ERROR("not long"); return NULL; } @@ -204,8 +204,8 @@ asn_build_int(data, datalength, type, intp, intsize) */ mask = 0x1FF << ((8 * (sizeof(int32) - 1)) - 1); /* mask is 0xFF800000 on a big-endian machine */ - while((((integer & mask) == 0) || ((integer & mask) == mask)) - && intsize > 1){ + while ((((integer & mask) == 0) || ((integer & mask) == mask)) + && intsize > 1) { intsize--; integer <<= 8; } @@ -217,8 +217,8 @@ asn_build_int(data, datalength, type, intp, intsize) *datalength -= intsize; mask = 0xFF << (8 * (sizeof(int32) - 1)); /* mask is 0xFF000000 on a big-endian machine */ - while(intsize--){ - *data++ = (u_char)((integer & mask) >> (8 * (sizeof(int32) - 1))); + while (intsize--) { + *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(int32) - 1))); integer <<= 8; } return data; @@ -237,11 +237,11 @@ asn_build_int(data, datalength, type, intp, intsize) */ u_char * asn_build_unsigned_int(data, datalength, type, intp, intsize) - u_char *data; /* IN - pointer to start of output buffer */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - asn type of object */ - u_long *intp; /* IN - pointer to start of long integer */ - int intsize; /* IN - size of *intp */ + u_char *data; /* IN - pointer to start of output buffer */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - asn type of object */ + u_long *intp; /* IN - pointer to start of long integer */ + int intsize; /* IN - size of *intp */ { /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* @@ -251,14 +251,14 @@ asn_build_unsigned_int(data, datalength, type, intp, intsize) u_long mask; int add_null_byte = 0; - if (intsize != sizeof (long)) { + if (intsize != sizeof(long)) { ERROR("not long"); return NULL; } integer = *intp; mask = 0xFF << (8 * (sizeof(int32) - 1)); /* mask is 0xFF000000 on a big-endian machine */ - if ((u_char)((integer & mask) >> (8 * (sizeof(int32) - 1))) & 0x80){ + if ((u_char) ((integer & mask) >> (8 * (sizeof(int32) - 1))) & 0x80) { /* if MSB is set */ add_null_byte = 1; intsize++; @@ -270,7 +270,7 @@ asn_build_unsigned_int(data, datalength, type, intp, intsize) */ mask = 0x1FF << ((8 * (sizeof(int32) - 1)) - 1); /* mask is 0xFF800000 on a big-endian machine */ - while((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1){ + while ((((integer & mask) == 0) || ((integer & mask) == mask)) && intsize > 1) { intsize--; integer <<= 8; } @@ -280,14 +280,14 @@ asn_build_unsigned_int(data, datalength, type, intp, intsize) if (*datalength < intsize) return NULL; *datalength -= intsize; - if (add_null_byte == 1){ + if (add_null_byte == 1) { *data++ = '\0'; intsize--; } mask = 0xFF << (8 * (sizeof(int32) - 1)); /* mask is 0xFF000000 on a big-endian machine */ - while(intsize--){ - *data++ = (u_char)((integer & mask) >> (8 * (sizeof(int32) - 1))); + while (intsize--) { + *data++ = (u_char) ((integer & mask) >> (8 * (sizeof(int32) - 1))); integer <<= 8; } return data; @@ -308,11 +308,11 @@ asn_build_unsigned_int(data, datalength, type, intp, intsize) */ u_char * asn_parse_string(data, datalength, type, string, strlength) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - asn type of object */ - u_char *string; /* IN/OUT - pointer to start of output buffer */ - int *strlength; /* IN/OUT - size of output buffer */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - asn type of object */ + u_char *string; /* IN/OUT - pointer to start of output buffer */ + int *strlength; /* IN/OUT - size of output buffer */ { /* * ASN.1 octet string ::= primstring | cmpdstring @@ -320,23 +320,23 @@ asn_parse_string(data, datalength, type, string, strlength) * cmpdstring ::= 0x24 asnlength string {string}* */ u_char *bufp = data; - u_long asn_length; + u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (bufp == NULL) return NULL; - if (asn_length + (bufp - data) > *datalength){ + if (asn_length + (bufp - data) > *datalength) { ERROR("overflow of message"); return NULL; } - if (asn_length > *strlength){ + if (asn_length > *strlength) { ERROR("I don't support such long strings"); return NULL; } - bcopy((char *)bufp, (char *)string, (int)asn_length); - *strlength = (int)asn_length; - *datalength -= (int)asn_length + (bufp - data); + bcopy((char *) bufp, (char *) string, (int) asn_length); + *strlength = (int) asn_length; + *datalength -= (int) asn_length + (bufp - data); return bufp + asn_length; } @@ -353,11 +353,11 @@ asn_parse_string(data, datalength, type, string, strlength) */ u_char * asn_build_string(data, datalength, type, string, strlength) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - ASN type of string */ - u_char *string; /* IN - pointer to start of input buffer */ - int strlength; /* IN - size of input buffer */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - ASN type of string */ + u_char *string; /* IN - pointer to start of input buffer */ + int strlength; /* IN - size of input buffer */ { /* * ASN.1 octet string ::= primstring | cmpdstring @@ -370,7 +370,7 @@ asn_build_string(data, datalength, type, string, strlength) return NULL; if (*datalength < strlength) return NULL; - bcopy((char *)string, (char *)data, strlength); + bcopy((char *) string, (char *) data, strlength); *datalength -= strlength; return data + strlength; } @@ -387,9 +387,9 @@ asn_build_string(data, datalength, type, string, strlength) */ u_char * asn_parse_header(data, datalength, type) - u_char *data; /* IN - pointer to start of object */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - ASN type of object */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - ASN type of object */ { u_char *bufp = data; int header_len; @@ -398,9 +398,8 @@ asn_parse_header(data, datalength, type) if (*datalength <= 0) { return NULL; } - /* this only works on data types < 30, i.e. no extension octets */ - if (IS_EXTENSION_ID(*bufp)){ + if (IS_EXTENSION_ID(*bufp)) { ERROR("can't process ID >= 30"); return NULL; } @@ -409,11 +408,11 @@ asn_parse_header(data, datalength, type) if (bufp == NULL) return NULL; header_len = bufp - data; - if (header_len + asn_length > *datalength){ + if (header_len + asn_length > *datalength) { ERROR("asn length too long"); return NULL; } - *datalength = (int)asn_length; + *datalength = (int) asn_length; return bufp; } @@ -432,17 +431,17 @@ asn_parse_header(data, datalength, type) */ u_char * asn_build_header(data, datalength, type, length) - u_char *data; /* IN - pointer to start of object */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - ASN type of object */ - int length; /* IN - length of object */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - ASN type of object */ + int length; /* IN - length of object */ { if (*datalength < 1) return NULL; *data++ = type; (*datalength)--; return asn_build_length(data, datalength, length); - + } /* @@ -460,20 +459,20 @@ asn_build_header(data, datalength, type, length) */ u_char * asn_build_sequence(data, datalength, type, length) - u_char *data; /* IN - pointer to start of object */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - ASN type of object */ - int length; /* IN - length of object */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - ASN type of object */ + int length; /* IN - length of object */ { *datalength -= 4; - if (*datalength < 0){ + if (*datalength < 0) { *datalength += 4; /* fix up before punting */ return NULL; } *data++ = type; - *data++ = (u_char)(0x02 | ASN_LONG_LEN); - *data++ = (u_char)((length >> 8) & 0xFF); - *data++ = (u_char)(length & 0xFF); + *data++ = (u_char) (0x02 | ASN_LONG_LEN); + *data++ = (u_char) ((length >> 8) & 0xFF); + *data++ = (u_char) (length & 0xFF); return data; } @@ -487,63 +486,63 @@ asn_build_sequence(data, datalength, type, length) */ u_char * asn_parse_length(data, length) - u_char *data; /* IN - pointer to start of length field */ - u_long *length; /* OUT - value of length field */ + u_char *data; /* IN - pointer to start of length field */ + u_long *length; /* OUT - value of length field */ { u_char lengthbyte = *data; *length = 0; - if (lengthbyte & ASN_LONG_LEN){ + if (lengthbyte & ASN_LONG_LEN) { lengthbyte &= ~ASN_LONG_LEN; /* turn MSb off */ - if (lengthbyte == 0){ + if (lengthbyte == 0) { ERROR("We don't support indefinite lengths"); return NULL; } - if (lengthbyte > sizeof(long)){ + if (lengthbyte > sizeof(long)) { ERROR("we can't support data lengths that long"); return NULL; } - bcopy((char *)data + 1, (char *)length, (int)lengthbyte); + bcopy((char *) data + 1, (char *) length, (int) lengthbyte); /* XXX: is this useable on a 64bit platform ? */ *length = ntohl(*length); - *length >>= (8 * ((sizeof (*length)) - lengthbyte)); + *length >>= (8 * ((sizeof(*length)) - lengthbyte)); return data + lengthbyte + 1; - } else { /* short asnlength */ - *length = (long)lengthbyte; + } else { /* short asnlength */ + *length = (long) lengthbyte; return data + 1; } } u_char * asn_build_length(data, datalength, length) - u_char *data; /* IN - pointer to start of object */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - int length; /* IN - length of object */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + int length; /* IN - length of object */ { - u_char *start_data = data; + u_char *start_data = data; /* no indefinite lengths sent */ - if (length < 0x80){ - if (*datalength < 1){ + if (length < 0x80) { + if (*datalength < 1) { ERROR("build_length"); return NULL; - } - *data++ = (u_char)length; - } else if (length <= 0xFF){ - if (*datalength < 2){ + } + *data++ = (u_char) length; + } else if (length <= 0xFF) { + if (*datalength < 2) { ERROR("build_length"); return NULL; - } - *data++ = (u_char)(0x01 | ASN_LONG_LEN); - *data++ = (u_char)length; - } else { /* 0xFF < length <= 0xFFFF */ - if (*datalength < 3){ + } + *data++ = (u_char) (0x01 | ASN_LONG_LEN); + *data++ = (u_char) length; + } else { /* 0xFF < length <= 0xFFFF */ + if (*datalength < 3) { ERROR("build_length"); return NULL; - } - *data++ = (u_char)(0x02 | ASN_LONG_LEN); - *data++ = (u_char)((length >> 8) & 0xFF); - *data++ = (u_char)(length & 0xFF); + } + *data++ = (u_char) (0x02 | ASN_LONG_LEN); + *data++ = (u_char) ((length >> 8) & 0xFF); + *data++ = (u_char) (length & 0xFF); } *datalength -= (data - start_data); return data; @@ -564,11 +563,11 @@ asn_build_length(data, datalength, length) */ u_char * asn_parse_objid(data, datalength, type, objid, objidlength) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - ASN type of object */ - oid *objid; /* IN/OUT - pointer to start of output buffer */ - int *objidlength; /* IN/OUT - number of sub-id's in objid */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - ASN type of object */ + oid *objid; /* IN/OUT - pointer to start of output buffer */ + int *objidlength; /* IN/OUT - number of sub-id's in objid */ { /* * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* @@ -579,54 +578,54 @@ asn_parse_objid(data, datalength, type, objid, objidlength) u_char *bufp = data; oid *oidp = objid + 1; u_long subidentifier; - long length; - u_long asn_length; + long length; + u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (bufp == NULL) return NULL; - if (asn_length + (bufp - data) > *datalength){ + if (asn_length + (bufp - data) > *datalength) { ERROR("overflow of message"); return NULL; } - *datalength -= (int)asn_length + (bufp - data); + *datalength -= (int) asn_length + (bufp - data); /* Handle invalid object identifier encodings of the form 06 00 robustly */ if (asn_length == 0) objid[0] = objid[1] = 0; length = asn_length; - (*objidlength)--; /* account for expansion of first byte */ - while (length > 0 && (*objidlength)-- > 0){ + (*objidlength)--; /* account for expansion of first byte */ + while (length > 0 && (*objidlength)-- > 0) { subidentifier = 0; - do { /* shift and add in low order 7 bits */ - subidentifier = (subidentifier << 7) + (*(u_char *)bufp & ~ASN_BIT8); + do { /* shift and add in low order 7 bits */ + subidentifier = (subidentifier << 7) + (*(u_char *) bufp & ~ASN_BIT8); length--; - } while (*(u_char *)bufp++ & ASN_BIT8); /* last byte has high bit clear */ - if (subidentifier > (u_long)MAX_SUBID){ + } while (*(u_char *) bufp++ & ASN_BIT8); /* last byte has high bit clear */ + if (subidentifier > (u_long) MAX_SUBID) { ERROR("subidentifier too long"); return NULL; } - *oidp++ = (oid)subidentifier; + *oidp++ = (oid) subidentifier; } /* * The first two subidentifiers are encoded into the first component * with the value (X * 40) + Y, where: - * X is the value of the first subidentifier. + * X is the value of the first subidentifier. * Y is the value of the second subidentifier. */ - subidentifier = (u_long)objid[1]; - if (subidentifier == 0x2B){ + subidentifier = (u_long) objid[1]; + if (subidentifier == 0x2B) { objid[0] = 1; objid[1] = 3; } else { - objid[1] = (u_char)(subidentifier % 40); - objid[0] = (u_char)((subidentifier - objid[1]) / 40); + objid[1] = (u_char) (subidentifier % 40); + objid[0] = (u_char) ((subidentifier - objid[1]) / 40); } - *objidlength = (int)(oidp - objid); + *objidlength = (int) (oidp - objid); return bufp; } @@ -643,11 +642,11 @@ asn_parse_objid(data, datalength, type, objid, objidlength) */ u_char * asn_build_objid(data, datalength, type, objid, objidlength) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - ASN type of object */ - oid *objid; /* IN - pointer to start of input buffer */ - int objidlength; /* IN - number of sub-id's in objid */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - ASN type of object */ + oid *objid; /* IN - pointer to start of input buffer */ + int objidlength; /* IN - number of sub-id's in objid */ { /* * ASN.1 objid ::= 0x06 asnlength subidentifier {subidentifier}* @@ -658,11 +657,11 @@ asn_build_objid(data, datalength, type, objid, objidlength) u_char buf[MAX_OID_LEN]; u_char *bp = buf; oid *op = objid; - int asnlength; + int asnlength; u_long subid, mask, testmask; int bits, testbits; - if (objidlength < 2){ + if (objidlength < 2) { *bp++ = 0; objidlength = 0; } else { @@ -671,29 +670,29 @@ asn_build_objid(data, datalength, type, objid, objidlength) op += 2; } - while(objidlength-- > 0){ + while (objidlength-- > 0) { subid = *op++; - if (subid < 127){ /* off by one? */ + if (subid < 127) { /* off by one? */ *bp++ = subid; } else { - mask = 0x7F; /* handle subid == 0 case */ + mask = 0x7F; /* handle subid == 0 case */ bits = 0; /* testmask *MUST* !!!! be of an unsigned type */ - for(testmask = 0x7F, testbits = 0; testmask != 0; - testmask <<= 7, testbits += 7){ - if (subid & testmask){ /* if any bits set */ + for (testmask = 0x7F, testbits = 0; testmask != 0; + testmask <<= 7, testbits += 7) { + if (subid & testmask) { /* if any bits set */ mask = testmask; bits = testbits; } } /* mask can't be zero here */ - for(;mask != 0x7F; mask >>= 7, bits -= 7){ + for (; mask != 0x7F; mask >>= 7, bits -= 7) { /* fix a mask that got truncated above */ - if (mask == 0x1E00000) + if (mask == 0x1E00000) mask = 0xFE00000; - *bp++ = (u_char)(((subid & mask) >> bits) | ASN_BIT8); + *bp++ = (u_char) (((subid & mask) >> bits) | ASN_BIT8); } - *bp++ = (u_char)(subid & mask); + *bp++ = (u_char) (subid & mask); } } asnlength = bp - buf; @@ -702,7 +701,7 @@ asn_build_objid(data, datalength, type, objid, objidlength) return NULL; if (*datalength < asnlength) return NULL; - bcopy((char *)buf, (char *)data, asnlength); + bcopy((char *) buf, (char *) data, asnlength); *datalength -= asnlength; return data + asnlength; } @@ -719,21 +718,21 @@ asn_build_objid(data, datalength, type, objid, objidlength) */ u_char * asn_parse_null(data, datalength, type) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - ASN type of object */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - ASN type of object */ { /* * ASN.1 null ::= 0x05 0x00 */ - u_char *bufp = data; - u_long asn_length; + u_char *bufp = data; + u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (bufp == NULL) return NULL; - if (asn_length != 0){ + if (asn_length != 0) { ERROR("Malformed NULL"); return NULL; } @@ -754,9 +753,9 @@ asn_parse_null(data, datalength, type) */ u_char * asn_build_null(data, datalength, type) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - ASN type of object */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - ASN type of object */ { /* * ASN.1 null ::= 0x05 0x00 @@ -778,41 +777,41 @@ asn_build_null(data, datalength, type) */ u_char * asn_parse_bitstring(data, datalength, type, string, strlength) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - asn type of object */ - u_char *string; /* IN/OUT - pointer to start of output buffer */ - int *strlength; /* IN/OUT - size of output buffer */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - asn type of object */ + u_char *string; /* IN/OUT - pointer to start of output buffer */ + int *strlength; /* IN/OUT - size of output buffer */ { /* * bitstring ::= 0x03 asnlength unused {byte}* */ u_char *bufp = data; - u_long asn_length; + u_long asn_length; *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); if (bufp == NULL) return NULL; - if (asn_length + (bufp - data) > *datalength){ + if (asn_length + (bufp - data) > *datalength) { ERROR("overflow of message"); return NULL; } - if (asn_length > *strlength){ + if (asn_length > *strlength) { ERROR("I don't support such long bitstrings"); return NULL; } - if (asn_length < 1){ + if (asn_length < 1) { ERROR("Invalid bitstring"); return NULL; } - if (/** *bufp < 0 || **/ *bufp > 7){ + if ( /** *bufp < 0 || **/ *bufp > 7) { ERROR("Invalid bitstring"); return NULL; } - bcopy((char *)bufp, (char *)string, (int)asn_length); - *strlength = (int)asn_length; - *datalength -= (int)asn_length + (bufp - data); + bcopy((char *) bufp, (char *) string, (int) asn_length); + *strlength = (int) asn_length; + *datalength -= (int) asn_length + (bufp - data); return bufp + asn_length; } @@ -830,16 +829,16 @@ asn_parse_bitstring(data, datalength, type, string, strlength) */ u_char * asn_build_bitstring(data, datalength, type, string, strlength) - u_char *data; /* IN - pointer to start of object */ - int *datalength; /* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - ASN type of string */ - u_char *string; /* IN - pointer to start of input buffer */ - int strlength; /* IN - size of input buffer */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - ASN type of string */ + u_char *string; /* IN - pointer to start of input buffer */ + int strlength; /* IN - size of input buffer */ { /* * ASN.1 bit string ::= 0x03 asnlength unused {byte}* */ - if (strlength < 1 || /** *string < 0 || **/ *string > 7){ + if (strlength < 1 || /** *string < 0 || **/ *string > 7) { ERROR("Building invalid bitstring"); return NULL; } @@ -848,7 +847,7 @@ asn_build_bitstring(data, datalength, type, string, strlength) return NULL; if (*datalength < strlength) return NULL; - bcopy((char *)string, (char *)data, strlength); + bcopy((char *) string, (char *) data, strlength); *datalength -= strlength; return data + strlength; } @@ -867,45 +866,45 @@ asn_build_bitstring(data, datalength, type, string, strlength) */ u_char * asn_parse_unsigned_int64(data, datalength, type, cp, countersize) - u_char *data; /* IN - pointer to start of object */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char *type; /* OUT - asn type of object */ - struct counter64 *cp; /* IN/OUT -pointer to counter struct */ - int countersize;/* IN - size of output buffer */ + u_char *data; /* IN - pointer to start of object */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char *type; /* OUT - asn type of object */ + struct counter64 *cp; /* IN/OUT -pointer to counter struct */ + int countersize; /* IN - size of output buffer */ { /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* */ u_char *bufp = data; - u_long asn_length; + u_long asn_length; u_long low = 0, high = 0; int intsize = 4; - - if (countersize != sizeof(struct counter64)){ + + if (countersize != sizeof(struct counter64)) { ERROR("not counter64 size"); return NULL; } *type = *bufp++; bufp = asn_parse_length(bufp, &asn_length); - if (bufp == NULL){ + if (bufp == NULL) { ERROR("bad length"); return NULL; } - if (asn_length + (bufp - data) > *datalength){ + if (asn_length + (bufp - data) > *datalength) { ERROR("overflow of message"); return NULL; } if ((asn_length > (intsize * 2 + 1)) || - ((asn_length == (intsize * 2) + 1) && *bufp != 0x00)){ + ((asn_length == (intsize * 2) + 1) && *bufp != 0x00)) { ERROR("I don't support such large integers"); return NULL; } - *datalength -= (int)asn_length + (bufp - data); - if (*bufp & 0x80){ - low = -1; /* integer is negative */ + *datalength -= (int) asn_length + (bufp - data); + if (*bufp & 0x80) { + low = -1; /* integer is negative */ high = -1; } - while(asn_length--){ + while (asn_length--) { high = (high << 8) | ((low & 0xFF000000) >> 24); low = (low << 8) | *bufp++; } @@ -927,11 +926,11 @@ asn_parse_unsigned_int64(data, datalength, type, cp, countersize) */ u_char * asn_build_unsigned_int64(data, datalength, type, cp, countersize) - u_char *data; /* IN - pointer to start of output buffer */ - int *datalength;/* IN/OUT - number of valid bytes left in buffer */ - u_char type; /* IN - asn type of object */ - struct counter64 *cp; /* IN - pointer to counter struct */ - int countersize; /* IN - size of *intp */ + u_char *data; /* IN - pointer to start of output buffer */ + int *datalength; /* IN/OUT - number of valid bytes left in buffer */ + u_char type; /* IN - asn type of object */ + struct counter64 *cp; /* IN - pointer to counter struct */ + int countersize; /* IN - size of *intp */ { /* * ASN.1 integer ::= 0x02 asnlength byte {byte}* @@ -942,7 +941,7 @@ asn_build_unsigned_int64(data, datalength, type, cp, countersize) int add_null_byte = 0; int intsize; - if (countersize != sizeof (struct counter64)) { + if (countersize != sizeof(struct counter64)) { ERROR("not counter64 size"); return NULL; } @@ -951,7 +950,7 @@ asn_build_unsigned_int64(data, datalength, type, cp, countersize) high = cp->high; mask = 0xFF << (8 * (sizeof(int32) - 1)); /* mask is 0xFF000000 on a big-endian machine */ - if ((u_char)((high & mask) >> (8 * (sizeof(int32) - 1))) & 0x80) { + if ((u_char) ((high & mask) >> (8 * (sizeof(int32) - 1))) & 0x80) { /* if MSB is set */ add_null_byte = 1; intsize++; @@ -964,8 +963,8 @@ asn_build_unsigned_int64(data, datalength, type, cp, countersize) */ mask2 = 0x1FF << ((8 * (sizeof(int32) - 1)) - 1); /* mask2 is 0xFF800000 on a big-endian machine */ - while((((high & mask2) == 0) || ((high & mask2) == mask2)) - && intsize > 1){ + while ((((high & mask2) == 0) || ((high & mask2) == mask2)) + && intsize > 1) { intsize--; high = (high << 8) | ((low & mask) >> (8 * (sizeof(int32) - 1))); @@ -977,18 +976,16 @@ asn_build_unsigned_int64(data, datalength, type, cp, countersize) if (*datalength < intsize) return NULL; *datalength -= intsize; - if (add_null_byte == 1){ + if (add_null_byte == 1) { *data++ = '\0'; intsize--; } - while(intsize--){ - *data++ = (u_char)((high & mask) >> (8 * (sizeof(int32) - 1))); + while (intsize--) { + *data++ = (u_char) ((high & mask) >> (8 * (sizeof(int32) - 1))); high = (high << 8) | ((low & mask) >> (8 * (sizeof(int32) - 1))); low <<= 8; - + } return data; } - - diff --git a/snmplib/mib.c b/snmplib/mib.c index 98a0f8a908..11e168f350 100644 --- a/snmplib/mib.c +++ b/snmplib/mib.c @@ -1,3 +1,4 @@ + /********************************************************************** Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University @@ -19,20 +20,9 @@ WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ******************************************************************/ -#include -#include -#include -#include -#include #include "squid.h" -#ifdef linux -#include -#include -#endif - - #include "asn1.h" #include "snmp.h" #include "snmp_impl.h" @@ -54,10 +44,10 @@ static struct tree *get_symbol(); static char * uptimeString(timeticks, buf) - u_long timeticks; - char *buf; + u_long timeticks; + char *buf; { - int seconds, minutes, hours, days; + int seconds, minutes, hours, days; timeticks /= 100; days = timeticks / (60 * 60 * 24); @@ -69,24 +59,24 @@ uptimeString(timeticks, buf) minutes = timeticks / 60; seconds = timeticks % 60; - if (days == 0){ - snprintf(buf,32, "%d:%02d:%02d", hours, minutes, seconds); + if (days == 0) { + snprintf(buf, 32, "%d:%02d:%02d", hours, minutes, seconds); } else if (days == 1) { - snprintf(buf,32, "%d day, %d:%02d:%02d", days, hours, minutes, seconds); + snprintf(buf, 32, "%d day, %d:%02d:%02d", days, hours, minutes, seconds); } else { - snprintf(buf,32, "%d days, %d:%02d:%02d", days, hours, minutes, seconds); + snprintf(buf, 32, "%d days, %d:%02d:%02d", days, hours, minutes, seconds); } return buf; } static void sprint_hexstring(buf, cp, len) - char *buf; - u_char *cp; - int len; + char *buf; + u_char *cp; + int len; { - for(; len >= 16; len -= 16){ + for (; len >= 16; len -= 16) { sprintf(buf, "%02X %02X %02X %02X %02X %02X %02X %02X ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); buf += strlen(buf); cp += 8; @@ -94,7 +84,7 @@ sprint_hexstring(buf, cp, len) buf += strlen(buf); cp += 8; } - for(; len > 0; len--){ + for (; len > 0; len--) { sprintf(buf, "%02X ", *cp++); buf += strlen(buf); } @@ -103,14 +93,14 @@ sprint_hexstring(buf, cp, len) static void sprint_asciistring(buf, cp, len) - char *buf; - u_char *cp; - int len; + char *buf; + u_char *cp; + int len; { - int x; + int x; - for(x = 0; x < len; x++){ - if (isprint(*cp)){ + for (x = 0; x < len; x++) { + if (isprint(*cp)) { *buf++ = *cp++; } else { *buf++ = '.'; @@ -127,32 +117,32 @@ sprint_asciistring(buf, cp, len) #ifdef UNUSED int read_rawobjid(input, output, out_len) - char *input; - oid *output; - int *out_len; + char *input; + oid *output; + int *out_len; { - char buf[12], *cp; - oid *op = output; - u_long subid; + char buf[12], *cp; + oid *op = output; + u_long subid; - while(*input != '\0'){ + while (*input != '\0') { if (!isdigit(*input)) break; cp = buf; - while(isdigit(*input)) + while (isdigit(*input)) *cp++ = *input++; *cp = '\0'; subid = atoi(buf); - if(subid > MAX_SUBID){ + if (subid > MAX_SUBID) { fprintf(stderr, "sub-identifier too large: %s\n", buf); return 0; } - if((*out_len)-- <= 0){ + if ((*out_len)-- <= 0) { fprintf(stderr, "object identifier too long\n"); return 0; } *op++ = subid; - if(*input++ != '.') + if (*input++ != '.') break; } *out_len = op - output; @@ -164,49 +154,49 @@ read_rawobjid(input, output, out_len) #endif /* UNUSED */ /* - 0 - < 4 - hex - - 0 "" - < 4 hex Hex: oo oo oo - < 4 "fgh" Hex: oo oo oo - > 4 hex Hex: oo oo oo oo oo oo oo oo - > 4 "this is a test" - - */ + * 0 + * < 4 + * hex + * + * 0 "" + * < 4 hex Hex: oo oo oo + * < 4 "fgh" Hex: oo oo oo + * > 4 hex Hex: oo oo oo oo oo oo oo oo + * > 4 "this is a test" + * + */ static void sprint_octet_string(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { int hex, x; u_char *cp; - if (var->type != ASN_OCTET_STR){ + if (var->type != ASN_OCTET_STR) { sprintf(buf, "Wrong Type (should be OCTET STRING): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } hex = 0; - for(cp = var->val.string, x = 0; x < var->val_len; x++, cp++){ + for (cp = var->val.string, x = 0; x < var->val_len; x++, cp++) { if (!(isprint(*cp) || isspace(*cp))) hex = 1; } - if (var->val_len == 0){ + if (var->val_len == 0) { strcpy(buf, "\"\""); return; } - if (!hex){ + if (!hex) { *buf++ = '"'; sprint_asciistring(buf, var->val.string, var->val_len); buf += strlen(buf); *buf++ = '"'; *buf = '\0'; } - if (hex || var->val_len <= 4){ + if (hex || var->val_len <= 4) { sprintf(buf, " Hex: "); buf += strlen(buf); sprint_hexstring(buf, var->val.string, var->val_len); @@ -215,15 +205,15 @@ sprint_octet_string(buf, var, enums) static void sprint_opaque(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != OPAQUE){ + if (var->type != OPAQUE) { sprintf(buf, "Wrong Type (should be Opaque): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "OPAQUE: "); @@ -233,55 +223,55 @@ sprint_opaque(buf, var, enums) static void sprint_object_identifier(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != ASN_OBJECT_ID){ + if (var->type != ASN_OBJECT_ID) { sprintf(buf, "Wrong Type (should be OBJECT IDENTIFIER): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "OID: "); buf += strlen(buf); - sprint_objid(buf, (oid *)(var->val.objid), var->val_len / sizeof(oid)); + sprint_objid(buf, (oid *) (var->val.objid), var->val_len / sizeof(oid)); } static void sprint_timeticks(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { char timebuf[32]; - if (var->type != TIMETICKS){ + if (var->type != TIMETICKS) { sprintf(buf, "Wrong Type (should be Timeticks): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } - sprintf(buf, "Timeticks: (%ld) %s", *(u_long *)(var->val.integer), - uptimeString(*(u_long *)(var->val.integer), timebuf)); + sprintf(buf, "Timeticks: (%ld) %s", *(u_long *) (var->val.integer), + uptimeString(*(u_long *) (var->val.integer), timebuf)); } static void sprint_integer(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - char *enum_string = NULL; + char *enum_string = NULL; - if (var->type != ASN_INTEGER){ + if (var->type != ASN_INTEGER) { sprintf(buf, "Wrong Type (should be INTEGER): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } for (; enums; enums = enums->next) - if (enums->value == *var->val.integer){ + if (enums->value == *var->val.integer) { enum_string = enums->label; break; } @@ -293,20 +283,20 @@ sprint_integer(buf, var, enums) static void sprint_uinteger(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - char *enum_string = NULL; + char *enum_string = NULL; - if (var->type != UINTEGER){ + if (var->type != UINTEGER) { sprintf(buf, "Wrong Type (should be UInteger32): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } for (; enums; enums = enums->next) - if (enums->value == *var->val.integer){ + if (enums->value == *var->val.integer) { enum_string = enums->label; break; } @@ -318,14 +308,14 @@ sprint_uinteger(buf, var, enums) static void sprint_gauge(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != GAUGE){ + if (var->type != GAUGE) { sprintf(buf, "Wrong Type (should be Gauge): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "Gauge: %lu", *var->val.integer); @@ -333,14 +323,14 @@ sprint_gauge(buf, var, enums) static void sprint_counter(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != COUNTER){ + if (var->type != COUNTER) { sprintf(buf, "Wrong Type (should be Counter): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "%lu", *var->val.integer); @@ -348,18 +338,18 @@ sprint_counter(buf, var, enums) static void sprint_networkaddress(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { int x, len; u_char *cp; sprintf(buf, "Network Address: "); buf += strlen(buf); - cp = var->val.string; + cp = var->val.string; len = var->val_len; - for(x = 0; x < len; x++){ + for (x = 0; x < len; x++) { sprintf(buf, "%02X", *cp++); buf += strlen(buf); if (x < (len - 1)) @@ -369,33 +359,33 @@ sprint_networkaddress(buf, var, enums) static void sprint_ipaddress(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { u_char *ip; - if (var->type != IPADDRESS){ + if (var->type != IPADDRESS) { sprintf(buf, "Wrong Type (should be Ipaddress): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } ip = var->val.string; - sprintf(buf, "IpAddress: %d.%d.%d.%d",ip[0], ip[1], ip[2], ip[3]); + sprintf(buf, "IpAddress: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); } #if 0 static void sprint_unsigned_short(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != ASN_INTEGER){ + if (var->type != ASN_INTEGER) { sprintf(buf, "Wrong Type (should be INTEGER): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "INT: %lu", *var->val.integer); @@ -404,14 +394,14 @@ sprint_unsigned_short(buf, var, enums) static void sprint_null(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != ASN_NULL){ + if (var->type != ASN_NULL) { sprintf(buf, "Wrong Type (should be NULL): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "NULL"); @@ -419,18 +409,18 @@ sprint_null(buf, var, enums) static void sprint_bitstring(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { int len, bit; u_char *cp; char *enum_string; - if (var->type != ASN_BIT_STR){ + if (var->type != ASN_BIT_STR) { sprintf(buf, "Wrong Type (should be BIT STRING): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "BIT_STRING: "); @@ -439,12 +429,12 @@ sprint_bitstring(buf, var, enums) buf += strlen(buf); cp = var->val.bitstring + 1; - for(len = 0; len < var->val_len - 1; len++){ - for(bit = 0; bit < 8; bit++){ - if (*cp & (0x80 >> bit)){ + for (len = 0; len < var->val_len - 1; len++) { + for (bit = 0; bit < 8; bit++) { + if (*cp & (0x80 >> bit)) { enum_string = NULL; for (; enums; enums = enums->next) - if (enums->value == (len * 8) + bit){ + if (enums->value == (len * 8) + bit) { enum_string = enums->label; break; } @@ -455,20 +445,20 @@ sprint_bitstring(buf, var, enums) buf += strlen(buf); } } - cp ++; + cp++; } } static void sprint_nsapaddress(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != NSAP){ + if (var->type != NSAP) { sprintf(buf, "Wrong Type (should be NsapAddress): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } sprintf(buf, "NsapAddress: "); @@ -478,33 +468,33 @@ sprint_nsapaddress(buf, var, enums) static void sprint_counter64(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - if (var->type != COUNTER64){ + if (var->type != COUNTER64) { sprintf(buf, "Wrong Type (should be Counter64): "); buf += strlen(buf); - sprint_by_type(buf, var, (struct enum_list *)NULL); + sprint_by_type(buf, var, (struct enum_list *) NULL); return; } /* XXX */ sprintf(buf, "Counter64: "); buf += strlen(buf); - + sprint_hexstring(buf, &var->val.counter64->high, - sizeof(var->val.counter64->high)); + sizeof(var->val.counter64->high)); buf += strlen(buf); sprint_hexstring(buf, &var->val.counter64->low, - sizeof(var->val.counter64->low)); + sizeof(var->val.counter64->low)); } static void sprint_unknowntype(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { /* sprintf(buf, "Variable has bad type"); */ sprint_by_type(buf, var, NULL); @@ -512,59 +502,60 @@ sprint_unknowntype(buf, var, enums) static void sprint_badtype(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { sprintf(buf, "Variable has bad type"); } static void sprint_by_type(buf, var, enums) - char *buf; - struct variable_list *var; - struct enum_list *enums; + char *buf; + struct variable_list *var; + struct enum_list *enums; { - switch (var->type){ - case ASN_INTEGER: - sprint_integer(buf, var, enums); - break; - case ASN_OCTET_STR: - sprint_octet_string(buf, var, enums); - break; - case OPAQUE: - sprint_opaque(buf, var, enums); - break; - case ASN_OBJECT_ID: - sprint_object_identifier(buf, var, enums); - break; - case TIMETICKS: - sprint_timeticks(buf, var, enums); - break; - case GAUGE: - sprint_gauge(buf, var, enums); - break; - case COUNTER: - sprint_counter(buf, var, enums); - break; - case IPADDRESS: - sprint_ipaddress(buf, var, enums); - break; - case ASN_NULL: - sprint_null(buf, var, enums); - break; - case UINTEGER: - sprint_uinteger(buf, var, enums); - break; - default: - sprint_badtype(buf, var, enums); - break; + switch (var->type) { + case ASN_INTEGER: + sprint_integer(buf, var, enums); + break; + case ASN_OCTET_STR: + sprint_octet_string(buf, var, enums); + break; + case OPAQUE: + sprint_opaque(buf, var, enums); + break; + case ASN_OBJECT_ID: + sprint_object_identifier(buf, var, enums); + break; + case TIMETICKS: + sprint_timeticks(buf, var, enums); + break; + case GAUGE: + sprint_gauge(buf, var, enums); + break; + case COUNTER: + sprint_counter(buf, var, enums); + break; + case IPADDRESS: + sprint_ipaddress(buf, var, enums); + break; + case ASN_NULL: + sprint_null(buf, var, enums); + break; + case UINTEGER: + sprint_uinteger(buf, var, enums); + break; + default: + sprint_badtype(buf, var, enums); + break; } } struct tree *get_symbol(); -oid RFC1213_MIB[] = { 1, 3, 6, 1, 2, 1 }; +oid RFC1213_MIB[] = +{1, 3, 6, 1, 2, 1}; unsigned char RFC1213_MIB_text[] = ".iso.org.dod.internet.mgmt.mib-2"; unsigned char EXPERIMENTAL_MIB_text[] = ".iso.org.dod.internet.experimental"; unsigned char PRIVATE_MIB_text[] = ".iso.org.dod.internet.private"; @@ -588,26 +579,24 @@ init_mib() if (!Mib) Mib = read_mib("mib.txt"); #ifdef MIBFILEPATH - if (!Mib) - { - char tmp [1024]; - sprintf (tmp, "%s/mib.txt", MIBFILEPATH); + if (!Mib) { + char tmp[1024]; + sprintf(tmp, "%s/mib.txt", MIBFILEPATH); Mib = read_mib(tmp); - } + } #endif if (!Mib) Mib = read_mib("/etc/mib.txt"); - if (!Mib){ + if (!Mib) { fprintf(stderr, "Couldn't find mib file\n"); exit(2); } prefix = getenv("PREFIX"); - if (! prefix) { - prefix = Standard_Prefix; + if (!prefix) { + prefix = Standard_Prefix; } - /* save prefix: */ - snmp_new_prefix (prefix); + snmp_new_prefix(prefix); if (getenv("SUFFIX")) Suffix = TRUE; @@ -626,82 +615,84 @@ init_mib() */ char * -snmp_new_prefix (char *prefix) +snmp_new_prefix(char *prefix) { - char *lastchar; - int plen; - - if (prefix) { - lastchar = "."; - if (*prefix == '.') { prefix++; } - if ((plen = strlen (prefix))) { - lastchar = prefix + plen - 1; - } - strncpy (Prefix, prefix, sizeof (Prefix) - 2); - Prefix [sizeof (Prefix) - 2] = 0; - if (*lastchar != '.') { - Prefix [plen++] = '.'; - Prefix [plen] = 0; + char *lastchar; + int plen; + + if (prefix) { + lastchar = "."; + if (*prefix == '.') { + prefix++; + } + if ((plen = strlen(prefix))) { + lastchar = prefix + plen - 1; + } + strncpy(Prefix, prefix, sizeof(Prefix) - 2); + Prefix[sizeof(Prefix) - 2] = 0; + if (*lastchar != '.') { + Prefix[plen++] = '.'; + Prefix[plen] = 0; + } + return Prefix; } - return Prefix; - } - return (char *)NULL; + return (char *) NULL; } static void set_functions(subtree) - struct tree *subtree; + struct tree *subtree; { - for(; subtree; subtree = subtree->next_peer){ - switch(subtree->type){ - case TYPE_OBJID: - subtree->printer = sprint_object_identifier; - break; - case TYPE_OCTETSTR: - subtree->printer = sprint_octet_string; - break; - case TYPE_INTEGER: - subtree->printer = sprint_integer; - break; - case TYPE_NETADDR: - subtree->printer = sprint_networkaddress; - break; - case TYPE_IPADDR: - subtree->printer = sprint_ipaddress; - break; - case TYPE_COUNTER: - subtree->printer = sprint_counter; - break; - case TYPE_GAUGE: - subtree->printer = sprint_gauge; - break; - case TYPE_TIMETICKS: - subtree->printer = sprint_timeticks; - break; - case TYPE_OPAQUE: - subtree->printer = sprint_opaque; - break; - case TYPE_NULL: - subtree->printer = sprint_null; - break; - case TYPE_BITSTRING: - subtree->printer = sprint_bitstring; - break; - case TYPE_NSAPADDRESS: - subtree->printer = sprint_nsapaddress; - break; - case TYPE_COUNTER64: - subtree->printer = sprint_counter64; - break; - case TYPE_UINTEGER: - subtree->printer = sprint_uinteger; - break; - case TYPE_OTHER: - default: - subtree->printer = sprint_unknowntype; - break; + for (; subtree; subtree = subtree->next_peer) { + switch (subtree->type) { + case TYPE_OBJID: + subtree->printer = sprint_object_identifier; + break; + case TYPE_OCTETSTR: + subtree->printer = sprint_octet_string; + break; + case TYPE_INTEGER: + subtree->printer = sprint_integer; + break; + case TYPE_NETADDR: + subtree->printer = sprint_networkaddress; + break; + case TYPE_IPADDR: + subtree->printer = sprint_ipaddress; + break; + case TYPE_COUNTER: + subtree->printer = sprint_counter; + break; + case TYPE_GAUGE: + subtree->printer = sprint_gauge; + break; + case TYPE_TIMETICKS: + subtree->printer = sprint_timeticks; + break; + case TYPE_OPAQUE: + subtree->printer = sprint_opaque; + break; + case TYPE_NULL: + subtree->printer = sprint_null; + break; + case TYPE_BITSTRING: + subtree->printer = sprint_bitstring; + break; + case TYPE_NSAPADDRESS: + subtree->printer = sprint_nsapaddress; + break; + case TYPE_COUNTER64: + subtree->printer = sprint_counter64; + break; + case TYPE_UINTEGER: + subtree->printer = sprint_uinteger; + break; + case TYPE_OTHER: + default: + subtree->printer = sprint_unknowntype; + break; } set_functions(subtree->child_list); } @@ -715,7 +706,7 @@ main(argc, argv) char *argv[]; { oid objid[64]; - int objidlen = sizeof (objid); + int objidlen = sizeof(objid); int count; struct variable variable; @@ -726,31 +717,31 @@ main(argc, argv) variable.val.integer = 3; variable.val_len = 4; for (argc--; argc; argc--, argv++) { - objidlen = sizeof (objid); + objidlen = sizeof(objid); printf("read_objid(%s) = %d\n", - argv[1], read_objid(argv[1], objid, &objidlen)); - for(count = 0; count < objidlen; count++) + argv[1], read_objid(argv[1], objid, &objidlen)); + for (count = 0; count < objidlen; count++) printf("%d.", objid[count]); printf("\n"); print_variable(objid, objidlen, &variable); } } -#endif testing +#endif /* testing */ #if 0 static struct tree * find_rfc1213_mib(root) - struct tree *root; + struct tree *root; { oid *op = RFC1213_MIB; struct tree *tp; int len; - for(len = sizeof(RFC1213_MIB)/sizeof(oid); len; len--, op++){ - for(tp = root; tp; tp = tp->next_peer){ - if (tp->subid == *op){ + for (len = sizeof(RFC1213_MIB) / sizeof(oid); len; len--, op++) { + for (tp = root; tp; tp = tp->next_peer) { + if (tp->subid == *op) { root = tp->child_list; break; } @@ -762,31 +753,32 @@ find_rfc1213_mib(root) } #endif -int read_objid(input, output, out_len) - char *input; - oid *output; - int *out_len; /* number of subid's in "output" */ +int +read_objid(input, output, out_len) + char *input; + oid *output; + int *out_len; /* number of subid's in "output" */ { struct tree *root = Mib; oid *op = output; char buf[512]; - bzero (buf, sizeof(buf)); + bzero(buf, sizeof(buf)); if (*input == '.') input++; else { - strcpy(buf, Prefix); + strcpy(buf, Prefix); strcat(buf, input); input = buf; } - if (root == NULL){ + if (root == NULL) { fprintf(stderr, "Mib not initialized. Exiting.\n"); exit(1); } if ((*out_len = - parse_subtree(root, input, output, out_len)) == 0) + parse_subtree(root, input, output, out_len)) == 0) return (0); *out_len += output - op; @@ -794,10 +786,11 @@ int read_objid(input, output, out_len) } #ifdef notdef -int read_objid(input, output, out_len) - char *input; - oid *output; - int *out_len; /* number of subid's in "output" */ +int +read_objid(input, output, out_len) + char *input; + oid *output; + int *out_len; /* number of subid's in "output" */ { struct tree *root = Mib; oid *op = output; @@ -807,7 +800,7 @@ int read_objid(input, output, out_len) input++; else { root = find_rfc1213_mib(root); - for (i = 0; i < sizeof (RFC1213_MIB)/sizeof(oid); i++) { + for (i = 0; i < sizeof(RFC1213_MIB) / sizeof(oid); i++) { if ((*out_len)-- > 0) *output++ = RFC1213_MIB[i]; else { @@ -817,12 +810,12 @@ int read_objid(input, output, out_len) } } - if (root == NULL){ + if (root == NULL) { fprintf(stderr, "Mib not initialized. Exiting.\n"); exit(1); } if ((*out_len = - parse_subtree(root, input, output, out_len)) == 0) + parse_subtree(root, input, output, out_len)) == 0) return (0); *out_len += output - op; @@ -832,10 +825,10 @@ int read_objid(input, output, out_len) static int parse_subtree(subtree, input, output, out_len) - struct tree *subtree; - char *input; - oid *output; - int *out_len; /* number of subid's */ + struct tree *subtree; + char *input; + oid *output; + int *out_len; /* number of subid's */ { char buf[128], *to = buf; u_long subid = 0; @@ -862,13 +855,12 @@ parse_subtree(subtree, input, output, out_len) goto found; } tp = NULL; - } - else { + } else { /* * Read the name into a buffer. */ while ((*input != '\0') && - (*input != '.')) { + (*input != '.')) { *to++ = *input++; } *to = '\0'; @@ -892,13 +884,12 @@ parse_subtree(subtree, input, output, out_len) } } -found: - if(subid > (u_long)MAX_SUBID){ + found: + if (subid > (u_long) MAX_SUBID) { fprintf(stderr, "sub-identifier too large: %s\n", buf); return (0); } - - if ((*out_len)-- <= 0){ + if ((*out_len)-- <= 0) { fprintf(stderr, "object identifier too long\n"); return (0); } @@ -907,31 +898,30 @@ found: if (*input != '.') return (1); if ((*out_len = - parse_subtree(tp ? tp->child_list : NULL, ++input, output, out_len)) == 0) + parse_subtree(tp ? tp->child_list : NULL, ++input, output, out_len)) == 0) return (0); return (++*out_len); } void sprint_objid(buf, objid, objidlen) - char *buf; - oid *objid; - int objidlen; /* number of subidentifiers */ + char *buf; + oid *objid; + int objidlen; /* number of subidentifiers */ { - char tempbuf[2048], *cp; - struct tree *subtree = Mib; + char tempbuf[2048], *cp; + struct tree *subtree = Mib; - *tempbuf = '.'; /* this is a fully qualified name */ + *tempbuf = '.'; /* this is a fully qualified name */ get_symbol(objid, objidlen, subtree, tempbuf + 1); - if (Suffix){ - for(cp =tempbuf; *cp; cp++) - ; - while(cp >= tempbuf){ + if (Suffix) { + for (cp = tempbuf; *cp; cp++); + while (cp >= tempbuf) { if (isalpha(*cp)) break; cp--; } - while(cp >= tempbuf){ + while (cp >= tempbuf) { if (*cp == '.') break; cp--; @@ -942,30 +932,30 @@ sprint_objid(buf, objid, objidlen) } else { cp = tempbuf; - if ((strlen(tempbuf) > strlen((char *)RFC1213_MIB_text)) - && !bcmp(tempbuf, (char *)RFC1213_MIB_text, - strlen((char *)RFC1213_MIB_text))){ + if ((strlen(tempbuf) > strlen((char *) RFC1213_MIB_text)) + && !bcmp(tempbuf, (char *) RFC1213_MIB_text, + strlen((char *) RFC1213_MIB_text))) { cp += sizeof(RFC1213_MIB_text); } - if ((strlen(tempbuf) > strlen((char *)EXPERIMENTAL_MIB_text)) + if ((strlen(tempbuf) > strlen((char *) EXPERIMENTAL_MIB_text)) && !bcmp(tempbuf, (char *) EXPERIMENTAL_MIB_text, - strlen((char *)EXPERIMENTAL_MIB_text))){ - cp += sizeof(EXPERIMENTAL_MIB_text); + strlen((char *) EXPERIMENTAL_MIB_text))) { + cp += sizeof(EXPERIMENTAL_MIB_text); } - if ((strlen(tempbuf) > strlen((char *)PRIVATE_MIB_text)) + if ((strlen(tempbuf) > strlen((char *) PRIVATE_MIB_text)) && !bcmp(tempbuf, (char *) PRIVATE_MIB_text, - strlen((char *)PRIVATE_MIB_text))){ - cp += sizeof(PRIVATE_MIB_text); + strlen((char *) PRIVATE_MIB_text))) { + cp += sizeof(PRIVATE_MIB_text); } - if ((strlen(tempbuf) > strlen((char *)PARTY_MIB_text)) + if ((strlen(tempbuf) > strlen((char *) PARTY_MIB_text)) && !bcmp(tempbuf, (char *) PARTY_MIB_text, - strlen((char *)PARTY_MIB_text))){ - cp += sizeof(PARTY_MIB_text); + strlen((char *) PARTY_MIB_text))) { + cp += sizeof(PARTY_MIB_text); } - if ((strlen(tempbuf) > strlen((char *)SECRETS_MIB_text)) + if ((strlen(tempbuf) > strlen((char *) SECRETS_MIB_text)) && !bcmp(tempbuf, (char *) SECRETS_MIB_text, - strlen((char *)SECRETS_MIB_text))){ - cp += sizeof(SECRETS_MIB_text); + strlen((char *) SECRETS_MIB_text))) { + cp += sizeof(SECRETS_MIB_text); } } strcpy(buf, cp); @@ -974,10 +964,10 @@ sprint_objid(buf, objid, objidlen) void print_objid(objid, objidlen) - oid *objid; - int objidlen; /* number of subidentifiers */ + oid *objid; + int objidlen; /* number of subidentifiers */ { - char buf[256]; + char buf[256]; sprint_objid(buf, objid, objidlen); printf("%s\n", buf); @@ -986,11 +976,11 @@ print_objid(objid, objidlen) void print_variable(objid, objidlen, variable) - oid *objid; - int objidlen; - struct variable_list *variable; + oid *objid; + int objidlen; + struct variable_list *variable; { - char buf[2048]; + char buf[2048]; sprint_variable(buf, objid, objidlen, variable); printf("%s", buf); @@ -998,13 +988,13 @@ print_variable(objid, objidlen, variable) static void sprint_variable(buf, objid, objidlen, variable) - char *buf; - oid *objid; - int objidlen; - struct variable_list *variable; + char *buf; + oid *objid; + int objidlen; + struct variable_list *variable; { - char tempbuf[2048]; - struct tree *subtree = Mib; + char tempbuf[2048]; + struct tree *subtree = Mib; sprint_objid(buf, objid, objidlen); buf += strlen(buf); @@ -1018,11 +1008,11 @@ sprint_variable(buf, objid, objidlen, variable) else if (variable->type == SNMP_ENDOFMIBVIEW) sprintf(buf, "No more variables left in this MIB View\n"); else { - *tempbuf = '.'; /* this is a fully qualified name */ + *tempbuf = '.'; /* this is a fully qualified name */ subtree = get_symbol(objid, objidlen, subtree, tempbuf + 1); buf += strlen(buf); if (subtree->printer) - (*subtree->printer)(buf, variable, subtree->enums); + (*subtree->printer) (buf, variable, subtree->enums); else { sprint_by_type(buf, variable, subtree->enums); } @@ -1032,13 +1022,13 @@ sprint_variable(buf, objid, objidlen, variable) void sprint_value(buf, objid, objidlen, variable) - char *buf; - oid *objid; - int objidlen; - struct variable_list *variable; + char *buf; + oid *objid; + int objidlen; + struct variable_list *variable; { - char tempbuf[2048]; - struct tree *subtree = Mib; + char tempbuf[2048]; + struct tree *subtree = Mib; if (variable->type == SNMP_NOSUCHOBJECT) sprintf(buf, "No Such Object available on this agent\n"); @@ -1049,7 +1039,7 @@ sprint_value(buf, objid, objidlen, variable) else { subtree = get_symbol(objid, objidlen, subtree, tempbuf); if (subtree->printer) - (*subtree->printer)(buf, variable, subtree->enums); + (*subtree->printer) (buf, variable, subtree->enums); else { sprint_by_type(buf, variable, subtree->enums); } @@ -1058,11 +1048,11 @@ sprint_value(buf, objid, objidlen, variable) void print_value(objid, objidlen, variable) - oid *objid; - int objidlen; - struct variable_list *variable; + oid *objid; + int objidlen; + struct variable_list *variable; { - char tempbuf[2048]; + char tempbuf[2048]; sprint_value(tempbuf, objid, objidlen, variable); printf("%s\n", tempbuf); @@ -1070,38 +1060,38 @@ print_value(objid, objidlen, variable) static struct tree * get_symbol(objid, objidlen, subtree, buf) - oid *objid; - int objidlen; - struct tree *subtree; - char *buf; + oid *objid; + int objidlen; + struct tree *subtree; + char *buf; { - struct tree *return_tree = NULL; + struct tree *return_tree = NULL; - for(; subtree; subtree = subtree->next_peer){ - if (*objid == subtree->subid){ + for (; subtree; subtree = subtree->next_peer) { + if (*objid == subtree->subid) { strcpy(buf, subtree->label); goto found; } } /* subtree not found */ - while(objidlen--){ /* output rest of name, uninterpreted */ + while (objidlen--) { /* output rest of name, uninterpreted */ sprintf(buf, "%lu.", *objid++); - while(*buf) + while (*buf) buf++; } - *(buf - 1) = '\0'; /* remove trailing dot */ + *(buf - 1) = '\0'; /* remove trailing dot */ return NULL; -found: - if (objidlen > 1){ - while(*buf) + found: + if (objidlen > 1) { + while (*buf) buf++; *buf++ = '.'; *buf = '\0'; return_tree = get_symbol(objid + 1, objidlen - 1, subtree->child_list, - buf); - } + buf); + } if (return_tree != NULL) return return_tree; else @@ -1111,11 +1101,11 @@ found: static int lc_cmp(s1, s2) - char *s1, *s2; + char *s1, *s2; { char c1, c2; - while(*s1 && *s2){ + while (*s1 && *s2) { if (isupper(*s1)) c1 = tolower(*s1); else @@ -1142,42 +1132,42 @@ lc_cmp(s1, s2) */ static struct tree * get_tree(objid, objidlen, subtree) - oid *objid; - int objidlen; - struct tree *subtree; + oid *objid; + int objidlen; + struct tree *subtree; { - struct tree *return_tree = NULL; + struct tree *return_tree = NULL; - for(; subtree; subtree = subtree->next_peer){ - if (*objid == subtree->subid) - goto found; + for (; subtree; subtree = subtree->next_peer) { + if (*objid == subtree->subid) + goto found; } return NULL; -found: + found: if (objidlen > 1) - return_tree = get_tree(objid + 1, objidlen - 1, subtree->child_list); + return_tree = get_tree(objid + 1, objidlen - 1, subtree->child_list); if (return_tree != NULL) - return return_tree; + return return_tree; else - return subtree; + return subtree; } #if 0 static char * get_description(objid, objidlen) - oid *objid; - int objidlen; /* number of subidentifiers */ + oid *objid; + int objidlen; /* number of subidentifiers */ { - struct tree *subtree = Mib; + struct tree *subtree = Mib; subtree = get_tree(objid, objidlen, subtree); if (subtree) - return (subtree->description); + return (subtree->description); else - return NULL; + return NULL; } #endif @@ -1185,27 +1175,27 @@ get_description(objid, objidlen) #if 0 static void print_description(objid, objidlen) - oid *objid; - int objidlen; /* number of subidentifiers */ + oid *objid; + int objidlen; /* number of subidentifiers */ { char *desc = get_description(objid, objidlen); if (desc && desc[0] != '\0') - printf("Description: \"%s\"\n", desc); + printf("Description: \"%s\"\n", desc); else - printf("No description\n"); + printf("No description\n"); } #endif static struct tree * find_node(name, subtree) - char *name; - struct tree *subtree; + char *name; + struct tree *subtree; { struct tree *tp, *ret; - for(tp = subtree; tp; tp = tp->next_peer){ + for (tp = subtree; tp; tp = tp->next_peer) { if (!strcasecmp(name, tp->label)) return tp; ret = find_node(name, tp->child_list); @@ -1219,16 +1209,16 @@ find_node(name, subtree) #if 0 static int get_node(name, objid, objidlen) - char *name; - oid *objid; - int *objidlen; + char *name; + oid *objid; + int *objidlen; { struct tree *tp; oid newname[64], *op; tp = find_node(name, Mib); - if (tp){ - for(op = newname + 63; op >= newname; op--){ + if (tp) { + for (op = newname + 63; op >= newname; op--) { *op = tp->subid; tp = tp->parent; if (tp == NULL) @@ -1243,6 +1233,6 @@ get_node(name, objid, objidlen) return 0; } - + } #endif diff --git a/snmplib/parse.c b/snmplib/parse.c index dc1b239b1d..a01870f287 100644 --- a/snmplib/parse.c +++ b/snmplib/parse.c @@ -49,7 +49,7 @@ struct subid { /* use large token buffer in case of very long tokens: */ #define MAXTC 1024 -struct tc { /* textual conventions */ +struct tc { /* textual conventions */ int type; char descriptor[MAXTOKEN]; struct enum_list *enums; @@ -61,7 +61,7 @@ int Line = 1; #define SYNTAX_MASK 0x80 /* types of tokens - Tokens wiht the SYNTAX_MASK bit set are syntax tokens */ + * Tokens wiht the SYNTAX_MASK bit set are syntax tokens */ #define CONTINUE -1 #define ENDOFFILE 0 #define LABEL 1 @@ -78,7 +78,7 @@ int Line = 1; #define OPAQUE (12 | SYNTAX_MASK) #define NUL (13 | SYNTAX_MASK) #define SEQUENCE 14 -#define OF 15 /* SEQUENCE OF */ +#define OF 15 /* SEQUENCE OF */ #define OBJTYPE 16 #define ACCESS 17 #define READONLY 18 @@ -126,85 +126,86 @@ int Line = 1; #define SEMI 60 struct tok { - char *name; /* token name */ - int len; /* length not counting nul */ - int token; /* value */ - int hash; /* hash of name */ - struct tok *next; /* pointer to next in hash table */ + char *name; /* token name */ + int len; /* length not counting nul */ + int token; /* value */ + int hash; /* hash of name */ + struct tok *next; /* pointer to next in hash table */ }; -struct tok tokens[] = { - { "obsolete", sizeof ("obsolete")-1, OBSOLETE }, - { "Opaque", sizeof ("Opaque")-1, OPAQUE }, -/* { "recommended", sizeof("recommended")-1, RECOMMENDED }, */ - { "optional", sizeof ("optional")-1, OPTIONAL }, - { "LAST-UPDATED", sizeof ("LAST-UPDATED")-1, LASTUPDATED }, - { "ORGANIZATION", sizeof ("ORGANIZATION")-1, ORGANIZATION }, - { "CONTACT-INFO", sizeof ("CONTACT-INFO")-1, CONTACTINFO }, - { "MODULE-IDENTITY", sizeof ("MODULE-IDENTITY")-1, MODULEIDENTITY }, - { "MODULE-COMPLIANCE", sizeof ("MODULE-COMPLIANCE")-1, COMPLIANCE }, - { "DEFINITIONS", sizeof("DEFINITIONS")-1, DEFINITIONS}, - { "END", sizeof("END")-1, END}, - { ";", sizeof(";")-1, SEMI}, - { "AUGMENTS", sizeof ("AUGMENTS")-1, AUGMENTS }, - { "not-accessible", sizeof ("not-accessible")-1, NOACCESS }, - { "write-only", sizeof ("write-only")-1, WRITEONLY }, - { "NsapAddress", sizeof("NsapAddress")-1, NSAPADDRESS}, - { "UNITS", sizeof("Units")-1, UNITS}, - { "REFERENCE", sizeof("REFERENCE")-1, REFERENCE}, - { "NUM-ENTRIES", sizeof("NUM-ENTRIES")-1, NUM_ENTRIES}, - { "BITSTRING", sizeof("BitString")-1, BITSTRING}, - { "BIT", sizeof("BIT")-1, CONTINUE}, - { "Counter64", sizeof("Counter64")-1, COUNTER64}, - { "TimeTicks", sizeof ("TimeTicks")-1, TIMETICKS }, - { "NOTIFICATION-TYPE", sizeof ("NOTIFICATION-TYPE")-1, NOTIFTYPE }, - { "OBJECT-GROUP", sizeof ("OBJECT-GROUP")-1, OBJGROUP }, - { "OBJECTIDENTIFIER", sizeof ("OBJECTIDENTIFIER")-1, OBJID }, +struct tok tokens[] = +{ + {"obsolete", sizeof("obsolete") - 1, OBSOLETE}, + {"Opaque", sizeof("Opaque") - 1, OPAQUE}, +/* { "recommended", sizeof("recommended")-1, RECOMMENDED }, */ + {"optional", sizeof("optional") - 1, OPTIONAL}, + {"LAST-UPDATED", sizeof("LAST-UPDATED") - 1, LASTUPDATED}, + {"ORGANIZATION", sizeof("ORGANIZATION") - 1, ORGANIZATION}, + {"CONTACT-INFO", sizeof("CONTACT-INFO") - 1, CONTACTINFO}, + {"MODULE-IDENTITY", sizeof("MODULE-IDENTITY") - 1, MODULEIDENTITY}, + {"MODULE-COMPLIANCE", sizeof("MODULE-COMPLIANCE") - 1, COMPLIANCE}, + {"DEFINITIONS", sizeof("DEFINITIONS") - 1, DEFINITIONS}, + {"END", sizeof("END") - 1, END}, + {";", sizeof(";") - 1, SEMI}, + {"AUGMENTS", sizeof("AUGMENTS") - 1, AUGMENTS}, + {"not-accessible", sizeof("not-accessible") - 1, NOACCESS}, + {"write-only", sizeof("write-only") - 1, WRITEONLY}, + {"NsapAddress", sizeof("NsapAddress") - 1, NSAPADDRESS}, + {"UNITS", sizeof("Units") - 1, UNITS}, + {"REFERENCE", sizeof("REFERENCE") - 1, REFERENCE}, + {"NUM-ENTRIES", sizeof("NUM-ENTRIES") - 1, NUM_ENTRIES}, + {"BITSTRING", sizeof("BitString") - 1, BITSTRING}, + {"BIT", sizeof("BIT") - 1, CONTINUE}, + {"Counter64", sizeof("Counter64") - 1, COUNTER64}, + {"TimeTicks", sizeof("TimeTicks") - 1, TIMETICKS}, + {"NOTIFICATION-TYPE", sizeof("NOTIFICATION-TYPE") - 1, NOTIFTYPE}, + {"OBJECT-GROUP", sizeof("OBJECT-GROUP") - 1, OBJGROUP}, + {"OBJECTIDENTIFIER", sizeof("OBJECTIDENTIFIER") - 1, OBJID}, /* * This CONTINUE appends the next word onto OBJECT, * hopefully matching OBJECTIDENTIFIER above. */ - { "OBJECT", sizeof ("OBJECT")-1, CONTINUE }, - { "NetworkAddress", sizeof ("NetworkAddress")-1, NETADDR }, - { "Gauge", sizeof ("Gauge")-1, GAUGE }, - { "read-write", sizeof ("read-write")-1, READWRITE }, - { "read-create", sizeof ("read-create")-1, READCREATE }, - { "OCTETSTRING", sizeof ("OCTETSTRING")-1, OCTETSTR }, - { "OCTET", sizeof ("OCTET")-1, -1 }, - { "OF", sizeof ("OF")-1, OF }, - { "SEQUENCE", sizeof ("SEQUENCE")-1, SEQUENCE }, - { "NULL", sizeof ("NULL")-1, NUL }, - { "IpAddress", sizeof ("IpAddress")-1, IPADDR }, - { "UInteger32", sizeof ("UInteger32")-1, UINTEGER32 }, - { "INTEGER", sizeof ("INTEGER")-1, INTEGER }, - { "Counter", sizeof ("Counter")-1, COUNTER }, - { "read-only", sizeof ("read-only")-1, READONLY }, - { "DESCRIPTION", sizeof ("DESCRIPTION")-1, DESCRIPTION }, - { "INDEX", sizeof ("INDEX")-1, INDEX }, - { "DEFVAL", sizeof ("DEFVAL")-1, DEFVAL }, - { "deprecated", sizeof ("deprecated")-1, DEPRECATED }, - { "SIZE", sizeof ("SIZE")-1, SIZE }, - { "MAX-ACCESS", sizeof ("MAX-ACCESS")-1, ACCESS }, - { "ACCESS", sizeof ("ACCESS")-1, ACCESS }, - { "mandatory", sizeof ("mandatory")-1, MANDATORY }, - { "current", sizeof ("current")-1, CURRENT }, - { "STATUS", sizeof ("STATUS")-1, STATUS }, - { "SYNTAX", sizeof ("SYNTAX")-1, SYNTAX }, - { "OBJECT-TYPE", sizeof ("OBJECT-TYPE")-1, OBJTYPE }, - { "{", sizeof ("{")-1, LEFTBRACKET }, - { "}", sizeof ("}")-1, RIGHTBRACKET }, - { "::=", sizeof ("::=")-1, EQUALS }, - { "(", sizeof ("(")-1, LEFTPAREN }, - { ")", sizeof (")")-1, RIGHTPAREN }, - { ",", sizeof (",")-1, COMMA }, - { NULL } + {"OBJECT", sizeof("OBJECT") - 1, CONTINUE}, + {"NetworkAddress", sizeof("NetworkAddress") - 1, NETADDR}, + {"Gauge", sizeof("Gauge") - 1, GAUGE}, + {"read-write", sizeof("read-write") - 1, READWRITE}, + {"read-create", sizeof("read-create") - 1, READCREATE}, + {"OCTETSTRING", sizeof("OCTETSTRING") - 1, OCTETSTR}, + {"OCTET", sizeof("OCTET") - 1, -1}, + {"OF", sizeof("OF") - 1, OF}, + {"SEQUENCE", sizeof("SEQUENCE") - 1, SEQUENCE}, + {"NULL", sizeof("NULL") - 1, NUL}, + {"IpAddress", sizeof("IpAddress") - 1, IPADDR}, + {"UInteger32", sizeof("UInteger32") - 1, UINTEGER32}, + {"INTEGER", sizeof("INTEGER") - 1, INTEGER}, + {"Counter", sizeof("Counter") - 1, COUNTER}, + {"read-only", sizeof("read-only") - 1, READONLY}, + {"DESCRIPTION", sizeof("DESCRIPTION") - 1, DESCRIPTION}, + {"INDEX", sizeof("INDEX") - 1, INDEX}, + {"DEFVAL", sizeof("DEFVAL") - 1, DEFVAL}, + {"deprecated", sizeof("deprecated") - 1, DEPRECATED}, + {"SIZE", sizeof("SIZE") - 1, SIZE}, + {"MAX-ACCESS", sizeof("MAX-ACCESS") - 1, ACCESS}, + {"ACCESS", sizeof("ACCESS") - 1, ACCESS}, + {"mandatory", sizeof("mandatory") - 1, MANDATORY}, + {"current", sizeof("current") - 1, CURRENT}, + {"STATUS", sizeof("STATUS") - 1, STATUS}, + {"SYNTAX", sizeof("SYNTAX") - 1, SYNTAX}, + {"OBJECT-TYPE", sizeof("OBJECT-TYPE") - 1, OBJTYPE}, + {"{", sizeof("{") - 1, LEFTBRACKET}, + {"}", sizeof("}") - 1, RIGHTBRACKET}, + {"::=", sizeof("::=") - 1, EQUALS}, + {"(", sizeof("(") - 1, LEFTPAREN}, + {")", sizeof(")") - 1, RIGHTPAREN}, + {",", sizeof(",") - 1, COMMA}, + {NULL} }; #define HASHSIZE 32 #define BUCKET(x) (x & 0x01F) -struct tok *buckets[HASHSIZE]; +struct tok *buckets[HASHSIZE]; static void do_subtree(); static int get_token(); @@ -214,21 +215,21 @@ static int tossObjectIdentifier(); static void hash_init() { - struct tok *tp; - char *cp; - int h; - int b; - - bzero((char *)buckets, sizeof(buckets)); - for (tp = tokens; tp->name; tp++) { - for (h = 0, cp = tp->name; *cp; cp++) - h += *cp; - tp->hash = h; - b = BUCKET(h); - if (buckets[b]) - tp->next = buckets[b]; /* BUG ??? */ - buckets[b] = tp; - } + struct tok *tp; + char *cp; + int h; + int b; + + bzero((char *) buckets, sizeof(buckets)); + for (tp = tokens; tp->name; tp++) { + for (h = 0, cp = tp->name; *cp; cp++) + h += *cp; + tp->hash = h; + b = BUCKET(h); + if (buckets[b]) + tp->next = buckets[b]; /* BUG ??? */ + buckets[b] = tp; + } } #define NHASHSIZE 128 @@ -239,42 +240,42 @@ void init_node_hash(nodes) struct node *nodes; { - struct node *np, *nextp; - char *cp; - int hash; - - bzero((char *)nbuckets,sizeof(nbuckets)); - for(np = nodes; np;){ - nextp = np->next; - hash = 0; - for(cp = np->parent; *cp; cp++) - hash += *cp; - np->next = nbuckets[NBUCKET(hash)]; - nbuckets[NBUCKET(hash)] = np; - np = nextp; - } + struct node *np, *nextp; + char *cp; + int hash; + + bzero((char *) nbuckets, sizeof(nbuckets)); + for (np = nodes; np;) { + nextp = np->next; + hash = 0; + for (cp = np->parent; *cp; cp++) + hash += *cp; + np->next = nbuckets[NBUCKET(hash)]; + nbuckets[NBUCKET(hash)] = np; + np = nextp; + } } static char * Malloc(num) - unsigned num; + unsigned num; { #ifndef linux - char* calloc(); + char *calloc(); #endif - + /* this is to fix (what seems to be) a problem with the IBM RT C - library malloc */ + * library malloc */ if (num < 16) num = 16; - return (char *)calloc(1, num); + return (char *) calloc(1, num); } static void print_error(string, token, type) - char *string; - char *token; - int type; + char *string; + char *token; + int type; { if (type == ENDOFFILE) fprintf(stderr, "%s(EOF): On or around line %d\n", string, Line); @@ -286,22 +287,22 @@ print_error(string, token, type) #ifdef TEST print_subtree(tree, count) - struct tree *tree; - int count; + struct tree *tree; + int count; { struct tree *tp; int i; - for(i = 0; i < count; i++) + for (i = 0; i < count; i++) printf(" "); printf("Children of %s:\n", tree->label); count++; - for(tp = tree->child_list; tp; tp = tp->next_peer){ - for(i = 0; i < count; i++) + for (tp = tree->child_list; tp; tp = tp->next_peer) { + for (i = 0; i < count; i++) printf(" "); printf("%s\n", tp->label); } - for(tp = tree->child_list; tp; tp = tp->next_peer){ + for (tp = tree->child_list; tp; tp = tp->next_peer) { print_subtree(tp, count); } } @@ -314,71 +315,71 @@ build_translation_table() { int count; - for(count = 0; count < 256; count++){ - switch(count){ - case OBJID: - translation_table[count] = TYPE_OBJID; - break; - case OCTETSTR: - translation_table[count] = TYPE_OCTETSTR; - break; - case INTEGER: - translation_table[count] = TYPE_INTEGER; - break; - case NETADDR: - translation_table[count] = TYPE_IPADDR; - break; - case IPADDR: - translation_table[count] = TYPE_IPADDR; - break; - case COUNTER: - translation_table[count] = TYPE_COUNTER; - break; - case GAUGE: - translation_table[count] = TYPE_GAUGE; - break; - case TIMETICKS: - translation_table[count] = TYPE_TIMETICKS; - break; - case OPAQUE: - translation_table[count] = TYPE_OPAQUE; - break; - case NUL: - translation_table[count] = TYPE_NULL; - break; - case COUNTER64: - translation_table[count] = TYPE_COUNTER64; - break; - case BITSTRING: - translation_table[count] = TYPE_BITSTRING; - break; - case NSAPADDRESS: - translation_table[count] = TYPE_NSAPADDRESS; - break; - case UINTEGER32: - translation_table[count] = TYPE_UINTEGER; - break; - default: - translation_table[count] = TYPE_OTHER; - break; + for (count = 0; count < 256; count++) { + switch (count) { + case OBJID: + translation_table[count] = TYPE_OBJID; + break; + case OCTETSTR: + translation_table[count] = TYPE_OCTETSTR; + break; + case INTEGER: + translation_table[count] = TYPE_INTEGER; + break; + case NETADDR: + translation_table[count] = TYPE_IPADDR; + break; + case IPADDR: + translation_table[count] = TYPE_IPADDR; + break; + case COUNTER: + translation_table[count] = TYPE_COUNTER; + break; + case GAUGE: + translation_table[count] = TYPE_GAUGE; + break; + case TIMETICKS: + translation_table[count] = TYPE_TIMETICKS; + break; + case OPAQUE: + translation_table[count] = TYPE_OPAQUE; + break; + case NUL: + translation_table[count] = TYPE_NULL; + break; + case COUNTER64: + translation_table[count] = TYPE_COUNTER64; + break; + case BITSTRING: + translation_table[count] = TYPE_BITSTRING; + break; + case NSAPADDRESS: + translation_table[count] = TYPE_NSAPADDRESS; + break; + case UINTEGER32: + translation_table[count] = TYPE_UINTEGER; + break; + default: + translation_table[count] = TYPE_OTHER; + break; } } } static struct tree * build_tree(nodes) - struct node *nodes; + struct node *nodes; { struct node *np; struct tree *tp, *lasttp; int bucket, nodes_left = 0; - + build_translation_table(); /* grow tree from this root node */ init_node_hash(nodes); /* build root node */ - tp = (struct tree *)Malloc(sizeof(struct tree)); + tp = (struct tree *) Malloc(sizeof(struct tree)); tp->parent = NULL; tp->next_peer = NULL; tp->child_list = NULL; @@ -392,7 +393,7 @@ build_tree(nodes) lasttp = tp; /* build root node */ - tp = (struct tree *)Malloc(sizeof(struct tree)); + tp = (struct tree *) Malloc(sizeof(struct tree)); tp->parent = NULL; tp->next_peer = lasttp; tp->child_list = NULL; @@ -406,7 +407,7 @@ build_tree(nodes) lasttp = tp; /* build root node */ - tp = (struct tree *)Malloc(sizeof(struct tree)); + tp = (struct tree *) Malloc(sizeof(struct tree)); tp->parent = NULL; tp->next_peer = lasttp; tp->child_list = NULL; @@ -423,20 +424,20 @@ build_tree(nodes) print_subtree(tp, 0); #endif /* TEST */ /* If any nodes are left, the tree is probably inconsistent */ - for(bucket = 0; bucket < NHASHSIZE; bucket++){ - if (nbuckets[bucket]){ + for (bucket = 0; bucket < NHASHSIZE; bucket++) { + if (nbuckets[bucket]) { nodes_left = 1; break; } } - if (nodes_left){ + if (nodes_left) { fprintf(stderr, "The mib description doesn't seem to be consistent.\n"); fprintf(stderr, "Some nodes couldn't be linked under the \"iso\" tree.\n"); fprintf(stderr, "these nodes are left:\n"); - for(bucket = 0; bucket < NHASHSIZE; bucket++){ - for(np = nbuckets[bucket]; np; np = np->next) - fprintf(stderr, "%s ::= { %s %ld } (%d)\n", np->label, - np->parent, np->subid, np->type); + for (bucket = 0; bucket < NHASHSIZE; bucket++) { + for (np = nbuckets[bucket]; np; np = np->next) + fprintf(stderr, "%s ::= { %s %ld } (%d)\n", np->label, + np->parent, np->subid, np->type); } } return tp; @@ -448,8 +449,8 @@ build_tree(nodes) */ static void do_subtree(root, nodes) - struct tree *root; - struct node **nodes; + struct tree *root; + struct node **nodes; { struct tree *tp; struct tree *peer = NULL; @@ -457,19 +458,19 @@ do_subtree(root, nodes) struct node *oldnp = NULL, *child_list = NULL, *childp = NULL; char *cp; int hash; - + tp = root; hash = 0; - for(cp = tp->label; *cp; cp++) - hash += *cp; + for (cp = tp->label; *cp; cp++) + hash += *cp; headp = &nbuckets[NBUCKET(hash)]; /* * Search each of the nodes for one whose parent is root, and * move each into a separate list. */ - for(np = *headp; np; np = np->next){ - if ((*tp->label != *np->parent) || strcmp(tp->label, np->parent)){ - if ((*tp->label == *np->label) && !strcmp(tp->label, np->label)){ + for (np = *headp; np; np = np->next) { + if ((*tp->label != *np->parent) || strcmp(tp->label, np->parent)) { + if ((*tp->label == *np->label) && !strcmp(tp->label, np->label)) { /* if there is another node with the same label, assume that * any children after this point in the list belong to the other node. * This adds some scoping to the table and allows vendors to @@ -479,17 +480,17 @@ do_subtree(root, nodes) } oldnp = np; } else { - if (child_list == NULL){ - child_list = childp = np; /* first entry in child list */ + if (child_list == NULL) { + child_list = childp = np; /* first entry in child list */ } else { childp->next = np; childp = np; } /* take this node out of the node list */ - if (oldnp == NULL){ - *headp = np->next; /* fix root of node list */ + if (oldnp == NULL) { + *headp = np->next; /* fix root of node list */ } else { - oldnp->next = np->next; /* link around this node */ + oldnp->next = np->next; /* link around this node */ } } } @@ -498,8 +499,8 @@ do_subtree(root, nodes) /* * Take each element in the child list and place it into the tree. */ - for(np = child_list; np; np = np->next){ - tp = (struct tree *)Malloc(sizeof(struct tree)); + for (np = child_list; np; np = np->next) { + tp = (struct tree *) Malloc(sizeof(struct tree)); tp->parent = root; tp->next_peer = NULL; tp->child_list = NULL; @@ -508,21 +509,21 @@ do_subtree(root, nodes) tp->type = translation_table[np->type]; tp->enums = np->enums; np->enums = NULL; /* so we don't free them later */ - tp->description = np->description; /* steals memory from np */ - np->description = NULL; /* so we don't free it later */ - if (root->child_list == NULL){ + tp->description = np->description; /* steals memory from np */ + np->description = NULL; /* so we don't free it later */ + if (root->child_list == NULL) { root->child_list = tp; } else { peer->next_peer = tp; } peer = tp; -/* if (tp->type == TYPE_OTHER) */ - do_subtree(tp, nodes); /* recurse on this child if it isn't - an end node */ +/* if (tp->type == TYPE_OTHER) */ + do_subtree(tp, nodes); /* recurse on this child if it isn't + * an end node */ } /* free all nodes that were copied into tree */ oldnp = NULL; - for(np = child_list; np; np = np->next){ + for (np = child_list; np; np = np->next) { if (oldnp) free(oldnp); oldnp = np; @@ -539,41 +540,41 @@ do_subtree(root, nodes) * Returns NULL on error. */ static int -getoid(fp, oid, length) - FILE *fp; - struct subid *oid; /* an array of subids */ - int length; /* the length of the array */ +getoid(fp, oid, length) + FILE *fp; + struct subid *oid; /* an array of subids */ + int length; /* the length of the array */ { int count; int type; char token[MAXTOKEN]; char *cp; - if ((type = get_token(fp, token)) != LEFTBRACKET){ + if ((type = get_token(fp, token)) != LEFTBRACKET) { print_error("Expected \"{\"", token, type); return 0; } type = get_token(fp, token); - for(count = 0; count < length; count++, oid++){ + for (count = 0; count < length; count++, oid++) { oid->label = 0; oid->subid = -1; - if (type == RIGHTBRACKET){ + if (type == RIGHTBRACKET) { return count; - } else if (type != LABEL && type != NUMBER){ + } else if (type != LABEL && type != NUMBER) { print_error("Not valid for object identifier", token, type); return 0; } - if (type == LABEL){ + if (type == LABEL) { /* this entry has a label */ - cp = (char *)Malloc((unsigned)strlen(token) + 1); + cp = (char *) Malloc((unsigned) strlen(token) + 1); strcpy(cp, token); oid->label = cp; type = get_token(fp, token); - if (type == LEFTPAREN){ + if (type == LEFTPAREN) { type = get_token(fp, token); - if (type == NUMBER){ + if (type == NUMBER) { oid->subid = atoi(token); - if ((type = get_token(fp, token)) != RIGHTPAREN){ + if ((type = get_token(fp, token)) != RIGHTPAREN) { print_error("Unexpected a closing parenthesis", token, type); return 0; } @@ -597,17 +598,17 @@ getoid(fp, oid, length) static void free_node(np) - struct node *np; + struct node *np; { struct enum_list *ep, *tep; ep = np->enums; - while(ep){ + while (ep) { tep = ep; ep = ep->next; - free((char *)tep); + free((char *) tep); } - free((char *)np); + free((char *) np); } /* @@ -618,8 +619,8 @@ free_node(np) */ static struct node * parse_objectid(fp, name) - FILE *fp; - char *name; + FILE *fp; + char *name; { int type; char token[MAXTOKEN]; @@ -630,21 +631,21 @@ parse_objectid(fp, name) struct node *np, *root, *oldnp = NULL; type = get_token(fp, token); - if (type != EQUALS){ + if (type != EQUALS) { print_error("Bad format", token, type); return 0; } - if ((length = getoid(fp, oid, 32)) != 0){ - np = root = (struct node *)Malloc(sizeof(struct node)); - bzero((char *)np, sizeof(struct node)); + if ((length = getoid(fp, oid, 32)) != 0) { + np = root = (struct node *) Malloc(sizeof(struct node)); + bzero((char *) np, sizeof(struct node)); /* * For each parent-child subid pair in the subid array, * create a node and link it into the node list. */ - for(count = 0, op = oid, nop=oid+1; count < (length - 2); count++, - op++, nop++){ + for (count = 0, op = oid, nop = oid + 1; count < (length - 2); count++, + op++, nop++) { /* every node must have parent's name and child's name or number */ - if (op->label && (nop->label || (nop->subid != -1))){ + if (op->label && (nop->label || (nop->subid != -1))) { strcpy(np->parent, op->label); if (nop->label) strcpy(np->label, nop->label); @@ -653,28 +654,28 @@ parse_objectid(fp, name) np->type = 0; np->enums = 0; /* set up next entry */ - np->next = (struct node *)Malloc(sizeof(*np->next)); - bzero((char *)np->next, sizeof(struct node)); + np->next = (struct node *) Malloc(sizeof(*np->next)); + bzero((char *) np->next, sizeof(struct node)); oldnp = np; np = np->next; } } - np->next = (struct node *)NULL; + np->next = (struct node *) NULL; /* * The above loop took care of all but the last pair. This pair is taken * care of here. The name for this node is taken from the label for this * entry. * np still points to an unused entry. */ - if (count == (length - 2)){ - if (op->label){ + if (count == (length - 2)) { + if (op->label) { strcpy(np->parent, op->label); strcpy(np->label, name); if (nop->subid != -1) np->subid = nop->subid; else print_error("Warning: This entry is pretty silly", - np->label, type); + np->label, type); } else { free_node(np); if (oldnp) @@ -683,36 +684,36 @@ parse_objectid(fp, name) return NULL; } } else { - print_error("Missing end of oid", (char *)NULL, type); - free_node(np); /* the last node allocated wasn't used */ + print_error("Missing end of oid", (char *) NULL, type); + free_node(np); /* the last node allocated wasn't used */ if (oldnp) oldnp->next = NULL; return NULL; } /* free the oid array */ - for(count = 0, op = oid; count < length; count++, op++){ + for (count = 0, op = oid; count < length; count++, op++) { if (op->label) free(op->label); op->label = 0; } return root; } else { - print_error("Bad object identifier", (char *)NULL, type); + print_error("Bad object identifier", (char *) NULL, type); return 0; } } static int get_tc(descriptor, ep) - char *descriptor; - struct enum_list **ep; + char *descriptor; + struct enum_list **ep; { int i; - for(i = 0; i < MAXTC; i++){ + for (i = 0; i < MAXTC; i++) { if (tclist[i].type == 0) break; - if (!strcmp(descriptor, tclist[i].descriptor)){ + if (!strcmp(descriptor, tclist[i].descriptor)) { *ep = tclist[i].enums; return tclist[i].type; } @@ -726,21 +727,21 @@ get_tc(descriptor, ep) */ static int parse_asntype(fp, name, ntype, ntoken) - FILE *fp; - char *name; - int *ntype; - char *ntoken; + FILE *fp; + char *name; + int *ntype; + char *ntoken; { int type, i; char token[MAXTOKEN]; struct enum_list *ep = 0; struct tc *tcp; int level; - + type = get_token(fp, token); - if (type == SEQUENCE){ - while((type = get_token(fp, token)) != ENDOFFILE){ - if (type == RIGHTBRACKET){ + if (type == SEQUENCE) { + while ((type = get_token(fp, token)) != ENDOFFILE) { + if (type == RIGHTBRACKET) { *ntype = get_token(fp, ntoken); return 1; } @@ -748,48 +749,48 @@ parse_asntype(fp, name, ntype, ntoken) print_error("Expected \"}\"", token, type); return 0; } else { - if (!strcmp(token, "TEXTUAL-CONVENTION")){ + if (!strcmp(token, "TEXTUAL-CONVENTION")) { while (type != SYNTAX) type = get_token(fp, token); type = get_token(fp, token); } /* textual convention */ - for(i = 0; i < MAXTC; i++){ + for (i = 0; i < MAXTC; i++) { if (tclist[i].type == 0) break; } - if (i == MAXTC){ + if (i == MAXTC) { print_error("No more textual conventions possible.", token, type); return 0; } tcp = &tclist[i]; strcpy(tcp->descriptor, name); - if (!(type & SYNTAX_MASK)){ + if (!(type & SYNTAX_MASK)) { print_error("Textual convention doesn't map to real type.", token, - type); + type); return 0; } tcp->type = type; *ntype = get_token(fp, ntoken); - if (*ntype == LEFTPAREN){ + if (*ntype == LEFTPAREN) { level = 1; /* don't record any constraints for now */ - while(level > 0){ + while (level > 0) { *ntype = get_token(fp, ntoken); if (*ntype == LEFTPAREN) level++; if (*ntype == RIGHTPAREN) - level--; + level--; } *ntype = get_token(fp, ntoken); } else if (*ntype == LEFTBRACKET) { /* if there is an enumeration list, parse it */ - while((type = get_token(fp, token)) != ENDOFFILE){ + while ((type = get_token(fp, token)) != ENDOFFILE) { if (type == RIGHTBRACKET) break; - if (type == LABEL){ + if (type == LABEL) { /* this is an enumerated label */ - if (tcp->enums == 0){ + if (tcp->enums == 0) { ep = tcp->enums = (struct enum_list *) Malloc(sizeof(struct enum_list)); } else { @@ -800,30 +801,30 @@ parse_asntype(fp, name, ntype, ntoken) ep->next = 0; /* a reasonable approximation for the length */ ep->label = - (char *)Malloc((unsigned)strlen(token) + 1); + (char *) Malloc((unsigned) strlen(token) + 1); strcpy(ep->label, token); type = get_token(fp, token); - if (type != LEFTPAREN){ + if (type != LEFTPAREN) { print_error("Expected \"(\"", token, type); /* free_node(np); */ return 0; } type = get_token(fp, token); - if (type != NUMBER){ + if (type != NUMBER) { print_error("Expected integer", token, type); /* free_node(np); */ return 0; } ep->value = atoi(token); type = get_token(fp, token); - if (type != RIGHTPAREN){ + if (type != RIGHTPAREN) { print_error("Expected \")\"", token, type); /* free_node(np); */ return 0; } } } - if (type == ENDOFFILE){ + if (type == ENDOFFILE) { print_error("Expected \"}\"", token, type); /* free_node(np); */ return 0; @@ -841,8 +842,8 @@ parse_asntype(fp, name, ntype, ntoken) */ static struct node * parse_objecttype(fp, name) - FILE *fp; - char *name; + FILE *fp; + char *name; { int type; char token[MAXTOKEN]; @@ -855,19 +856,19 @@ parse_objecttype(fp, name) struct enum_list *ep = 0; type = get_token(fp, token); - if (type != SYNTAX){ + if (type != SYNTAX) { print_error("Bad format for OBJECT TYPE", token, type); return 0; } - np = (struct node *)Malloc(sizeof(struct node)); + np = (struct node *) Malloc(sizeof(struct node)); np->next = 0; np->enums = 0; - np->description = NULL; /* default to an empty description */ + np->description = NULL; /* default to an empty description */ type = get_token(fp, token); - if (type == LABEL){ + if (type == LABEL) { tctype = get_tc(token, &(np->enums)); #if 0 - if (tctype == LABEL){ + if (tctype == LABEL) { print_error("No known translation for type", token, type); return 0; } @@ -876,173 +877,172 @@ parse_objecttype(fp, name) } np->type = type; nexttype = get_token(fp, nexttoken); - switch(type){ - case SEQUENCE: - strcpy(syntax, token); - if (nexttype == OF){ - strcat(syntax, " "); - strcat(syntax, nexttoken); - nexttype = get_token(fp, nexttoken); - strcat(syntax, " "); - strcat(syntax, nexttoken); - nexttype = get_token(fp, nexttoken); - } - break; - case INTEGER: - case UINTEGER32: - strcpy(syntax, token); - if (nexttype == LEFTBRACKET) { - /* if there is an enumeration list, parse it */ - while((type = get_token(fp, token)) != ENDOFFILE){ - if (type == RIGHTBRACKET) - break; - if (type == LABEL){ - /* this is an enumerated label */ - if (np->enums == 0){ - ep = np->enums = (struct enum_list *) - Malloc(sizeof(struct enum_list)); - } else { - ep->next = (struct enum_list *) - Malloc(sizeof(struct enum_list)); - ep = ep->next; - } - ep->next = 0; - /* a reasonable approximation for the length */ - ep->label = - (char *)Malloc((unsigned)strlen(token) + 1); - strcpy(ep->label, token); - type = get_token(fp, token); - if (type != LEFTPAREN){ - print_error("Expected \"(\"", token, type); - free_node(np); - return 0; - } - type = get_token(fp, token); - if (type != NUMBER){ - print_error("Expected integer", token, type); - free_node(np); - return 0; - } - ep->value = atoi(token); - type = get_token(fp, token); - if (type != RIGHTPAREN){ - print_error("Expected \")\"", token, type); - free_node(np); - return 0; - } + switch (type) { + case SEQUENCE: + strcpy(syntax, token); + if (nexttype == OF) { + strcat(syntax, " "); + strcat(syntax, nexttoken); + nexttype = get_token(fp, nexttoken); + strcat(syntax, " "); + strcat(syntax, nexttoken); + nexttype = get_token(fp, nexttoken); + } + break; + case INTEGER: + case UINTEGER32: + strcpy(syntax, token); + if (nexttype == LEFTBRACKET) { + /* if there is an enumeration list, parse it */ + while ((type = get_token(fp, token)) != ENDOFFILE) { + if (type == RIGHTBRACKET) + break; + if (type == LABEL) { + /* this is an enumerated label */ + if (np->enums == 0) { + ep = np->enums = (struct enum_list *) + Malloc(sizeof(struct enum_list)); + } else { + ep->next = (struct enum_list *) + Malloc(sizeof(struct enum_list)); + ep = ep->next; + } + ep->next = 0; + /* a reasonable approximation for the length */ + ep->label = + (char *) Malloc((unsigned) strlen(token) + 1); + strcpy(ep->label, token); + type = get_token(fp, token); + if (type != LEFTPAREN) { + print_error("Expected \"(\"", token, type); + free_node(np); + return 0; + } + type = get_token(fp, token); + if (type != NUMBER) { + print_error("Expected integer", token, type); + free_node(np); + return 0; + } + ep->value = atoi(token); + type = get_token(fp, token); + if (type != RIGHTPAREN) { + print_error("Expected \")\"", token, type); + free_node(np); + return 0; } } - if (type == ENDOFFILE){ - print_error("Expected \"}\"", token, type); - free_node(np); - return 0; + } + if (type == ENDOFFILE) { + print_error("Expected \"}\"", token, type); + free_node(np); + return 0; + } + nexttype = get_token(fp, nexttoken); + } else if (nexttype == LEFTPAREN) { + /* ignore the "constrained integer" for now */ + nexttype = get_token(fp, nexttoken); + nexttype = get_token(fp, nexttoken); + nexttype = get_token(fp, nexttoken); + } + break; + case BITSTRING: + strcpy(syntax, token); + if (nexttype == LEFTBRACKET) { + /* if there is an enumeration list, parse it */ + while ((type = get_token(fp, token)) != ENDOFFILE) { + if (type == RIGHTBRACKET) + break; + if (type == LABEL) { + /* this is an enumerated label */ + if (np->enums == 0) { + ep = np->enums = (struct enum_list *) + Malloc(sizeof(struct enum_list)); + } else { + ep->next = (struct enum_list *) + Malloc(sizeof(struct enum_list)); + ep = ep->next; + } + ep->next = 0; + /* a reasonable approximation for the length */ + ep->label = + (char *) Malloc((unsigned) strlen(token) + 1); + strcpy(ep->label, token); + type = get_token(fp, token); + if (type != LEFTPAREN) { + print_error("Expected \"(\"", token, type); + free_node(np); + return 0; + } + type = get_token(fp, token); + if (type != NUMBER) { + print_error("Expected integer", token, type); + free_node(np); + return 0; + } + ep->value = atoi(token); + type = get_token(fp, token); + if (type != RIGHTPAREN) { + print_error("Expected \")\"", token, type); + free_node(np); + return 0; + } } - nexttype = get_token(fp, nexttoken); - } else if (nexttype == LEFTPAREN){ - /* ignore the "constrained integer" for now */ - nexttype = get_token(fp, nexttoken); - nexttype = get_token(fp, nexttoken); - nexttype = get_token(fp, nexttoken); } - break; - case BITSTRING: - strcpy(syntax, token); - if (nexttype == LEFTBRACKET) { - /* if there is an enumeration list, parse it */ - while((type = get_token(fp, token)) != ENDOFFILE){ - if (type == RIGHTBRACKET) + if (type == ENDOFFILE) { + print_error("Expected \"}\"", token, type); + free_node(np); + return 0; + } + nexttype = get_token(fp, nexttoken); + } else if (nexttype == LEFTPAREN) { + /* ignore the "constrained integer" for now */ + nexttype = get_token(fp, nexttoken); + nexttype = get_token(fp, nexttoken); + nexttype = get_token(fp, nexttoken); + } + break; + case OCTETSTR: + strcpy(syntax, token); + /* ignore the "constrained octet string" for now */ + if (nexttype == LEFTPAREN) { + nexttype = get_token(fp, nexttoken); + if (nexttype == SIZE) { + nexttype = get_token(fp, nexttoken); + if (nexttype == LEFTPAREN) { + nexttype = get_token(fp, nexttoken); /* 0..255 */ + nexttype = get_token(fp, nexttoken); /* ) */ + nexttype = get_token(fp, nexttoken); /* ) */ + if (nexttype == RIGHTPAREN) { + nexttype = get_token(fp, nexttoken); break; - if (type == LABEL){ - /* this is an enumerated label */ - if (np->enums == 0){ - ep = np->enums = (struct enum_list *) - Malloc(sizeof(struct enum_list)); - } else { - ep->next = (struct enum_list *) - Malloc(sizeof(struct enum_list)); - ep = ep->next; - } - ep->next = 0; - /* a reasonable approximation for the length */ - ep->label = - (char *)Malloc((unsigned)strlen(token) + 1); - strcpy(ep->label, token); - type = get_token(fp, token); - if (type != LEFTPAREN){ - print_error("Expected \"(\"", token, type); - free_node(np); - return 0; - } - type = get_token(fp, token); - if (type != NUMBER){ - print_error("Expected integer", token, type); - free_node(np); - return 0; - } - ep->value = atoi(token); - type = get_token(fp, token); - if (type != RIGHTPAREN){ - print_error("Expected \")\"", token, type); - free_node(np); - return 0; - } } } - if (type == ENDOFFILE){ - print_error("Expected \"}\"", token, type); - free_node(np); - return 0; - } - nexttype = get_token(fp, nexttoken); - } else if (nexttype == LEFTPAREN){ - /* ignore the "constrained integer" for now */ - nexttype = get_token(fp, nexttoken); - nexttype = get_token(fp, nexttoken); - nexttype = get_token(fp, nexttoken); } - break; - case OCTETSTR: - strcpy(syntax, token); - /* ignore the "constrained octet string" for now */ - if (nexttype == LEFTPAREN) { - nexttype = get_token(fp, nexttoken); - if (nexttype == SIZE) { - nexttype = get_token(fp, nexttoken); - if (nexttype == LEFTPAREN) { - nexttype = get_token(fp, nexttoken); /* 0..255 */ - nexttype = get_token(fp, nexttoken); /* ) */ - nexttype = get_token(fp, nexttoken); /* ) */ - if (nexttype == RIGHTPAREN) - { - nexttype = get_token(fp, nexttoken); - break; - } - } - } - print_error("Bad syntax", token, type); - free_node(np); - return 0; - } - break; - case OBJID: - case NETADDR: - case IPADDR: - case COUNTER: - case GAUGE: - case TIMETICKS: - case OPAQUE: - case NUL: - case LABEL: - case NSAPADDRESS: - case COUNTER64: - strcpy(syntax, token); - break; - default: print_error("Bad syntax", token, type); free_node(np); return 0; + } + break; + case OBJID: + case NETADDR: + case IPADDR: + case COUNTER: + case GAUGE: + case TIMETICKS: + case OPAQUE: + case NUL: + case LABEL: + case NSAPADDRESS: + case COUNTER64: + strcpy(syntax, token); + break; + default: + print_error("Bad syntax", token, type); + free_node(np); + return 0; } - if (nexttype == UNITS){ + if (nexttype == UNITS) { type = get_token(fp, token); if (type != QUOTESTRING) { print_error("Bad DESCRIPTION", token, type); @@ -1051,26 +1051,26 @@ parse_objecttype(fp, name) } nexttype = get_token(fp, nexttoken); } - if (nexttype != ACCESS){ + if (nexttype != ACCESS) { print_error("Should be ACCESS", nexttoken, nexttype); free_node(np); return 0; } type = get_token(fp, token); if (type != READONLY && type != READWRITE && type != WRITEONLY - && type != NOACCESS && type != READCREATE){ + && type != NOACCESS && type != READCREATE) { print_error("Bad access type", nexttoken, nexttype); free_node(np); return 0; } type = get_token(fp, token); - if (type != STATUS){ + if (type != STATUS) { print_error("Should be STATUS", token, nexttype); free_node(np); return 0; } type = get_token(fp, token); - if (type != MANDATORY && type != CURRENT && type != OPTIONAL && type != OBSOLETE && type != DEPRECATED){ + if (type != MANDATORY && type != CURRENT && type != OPTIONAL && type != OBSOLETE && type != DEPRECATED) { print_error("Bad status", token, type); free_node(np); return 0; @@ -1080,55 +1080,55 @@ parse_objecttype(fp, name) */ type = get_token(fp, token); while (type != EQUALS) { - switch (type) { - case DESCRIPTION: - type = get_token(fp, token); - if (type != QUOTESTRING) { - print_error("Bad DESCRIPTION", token, type); - free_node(np); - return 0; - } + switch (type) { + case DESCRIPTION: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } #ifdef TEST -printf("Description== \"%.50s\"\n", quoted_string_buffer); + printf("Description== \"%.50s\"\n", quoted_string_buffer); #endif - np->description = quoted_string_buffer; - quoted_string_buffer = (char *)calloc(1, MAXQUOTESTR); - break; + np->description = quoted_string_buffer; + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); + break; case REFERENCE: - type = get_token(fp, token); - if (type != QUOTESTRING) { - print_error("Bad DESCRIPTION", token, type); - free_node(np); - return 0; - } - break; - case INDEX: - case DEFVAL: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } + break; + case INDEX: + case DEFVAL: case AUGMENTS: case NUM_ENTRIES: - if (tossObjectIdentifier(fp) != OBJID) { - print_error("Bad Object Identifier", token, type); - free_node(np); - return 0; - } - break; - - default: - print_error("Bad format of optional clauses", token,type); - free_node(np); - return 0; - - } - type = get_token(fp, token); + if (tossObjectIdentifier(fp) != OBJID) { + print_error("Bad Object Identifier", token, type); + free_node(np); + return 0; + } + break; + + default: + print_error("Bad format of optional clauses", token, type); + free_node(np); + return 0; + + } + type = get_token(fp, token); } - if (type != EQUALS){ + if (type != EQUALS) { print_error("Bad format", token, type); free_node(np); return 0; } length = getoid(fp, oid, 32); - if (length > 1 && length <= 32){ + if (length > 1 && length <= 32) { /* just take the last pair in the oid list */ if (oid[length - 2].label) strncpy(np->parent, oid[length - 2].label, MAXLABEL); @@ -1138,12 +1138,12 @@ printf("Description== \"%.50s\"\n", quoted_string_buffer); else print_error("Warning: This entry is pretty silly", np->label, type); } else { - print_error("No end to oid", (char *)NULL, type); + print_error("No end to oid", (char *) NULL, type); free_node(np); np = 0; } /* free oid array */ - for(count = 0; count < length; count++){ + for (count = 0; count < length; count++) { if (oid[count].label) free(oid[count].label); oid[count].label = 0; @@ -1158,8 +1158,8 @@ printf("Description== \"%.50s\"\n", quoted_string_buffer); */ static struct node * parse_objectgroup(fp, name) - FILE *fp; - char *name; + FILE *fp; + char *name; { int type; char token[MAXTOKEN]; @@ -1167,36 +1167,36 @@ parse_objectgroup(fp, name) struct subid oid[32]; struct node *np; - np = (struct node *)Malloc(sizeof(struct node)); + np = (struct node *) Malloc(sizeof(struct node)); np->type = 0; np->next = 0; np->enums = 0; - np->description = NULL; /* default to an empty description */ + np->description = NULL; /* default to an empty description */ type = get_token(fp, token); while (type != EQUALS) { - switch (type) { - case DESCRIPTION: - type = get_token(fp, token); - if (type != QUOTESTRING) { - print_error("Bad DESCRIPTION", token, type); - free_node(np); - return 0; - } + switch (type) { + case DESCRIPTION: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } #ifdef TEST -printf("Description== \"%.50s\"\n", quoted_string_buffer); + printf("Description== \"%.50s\"\n", quoted_string_buffer); #endif - np->description = quoted_string_buffer; - quoted_string_buffer = (char *)calloc(1, MAXQUOTESTR); - break; - - default: - /* NOTHING */ - break; - } - type = get_token(fp, token); + np->description = quoted_string_buffer; + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); + break; + + default: + /* NOTHING */ + break; + } + type = get_token(fp, token); } length = getoid(fp, oid, 32); - if (length > 1 && length <= 32){ + if (length > 1 && length <= 32) { /* just take the last pair in the oid list */ if (oid[length - 2].label) strncpy(np->parent, oid[length - 2].label, MAXLABEL); @@ -1206,12 +1206,12 @@ printf("Description== \"%.50s\"\n", quoted_string_buffer); else print_error("Warning: This entry is pretty silly", np->label, type); } else { - print_error("No end to oid", (char *)NULL, type); + print_error("No end to oid", (char *) NULL, type); free_node(np); np = 0; } /* free oid array */ - for(count = 0; count < length; count++){ + for (count = 0; count < length; count++) { if (oid[count].label) free(oid[count].label); oid[count].label = 0; @@ -1225,8 +1225,8 @@ printf("Description== \"%.50s\"\n", quoted_string_buffer); */ static struct node * parse_notificationDefinition(fp, name) - FILE *fp; - char *name; + FILE *fp; + char *name; { int type; char token[MAXTOKEN]; @@ -1234,36 +1234,36 @@ parse_notificationDefinition(fp, name) struct subid oid[32]; struct node *np; - np = (struct node *)Malloc(sizeof(struct node)); + np = (struct node *) Malloc(sizeof(struct node)); np->type = 0; np->next = 0; np->enums = 0; - np->description = NULL; /* default to an empty description */ + np->description = NULL; /* default to an empty description */ type = get_token(fp, token); while (type != EQUALS) { - switch (type) { - case DESCRIPTION: - type = get_token(fp, token); - if (type != QUOTESTRING) { - print_error("Bad DESCRIPTION", token, type); - free_node(np); - return 0; - } + switch (type) { + case DESCRIPTION: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } #ifdef TEST -printf("Description== \"%.50s\"\n", quoted_string_buffer); + printf("Description== \"%.50s\"\n", quoted_string_buffer); #endif - np->description = quoted_string_buffer; - quoted_string_buffer = (char *)calloc(1, MAXQUOTESTR); - break; - - default: - /* NOTHING */ - break; - } - type = get_token(fp, token); + np->description = quoted_string_buffer; + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); + break; + + default: + /* NOTHING */ + break; + } + type = get_token(fp, token); } length = getoid(fp, oid, 32); - if (length > 1 && length <= 32){ + if (length > 1 && length <= 32) { /* just take the last pair in the oid list */ if (oid[length - 2].label) strncpy(np->parent, oid[length - 2].label, MAXLABEL); @@ -1273,12 +1273,12 @@ printf("Description== \"%.50s\"\n", quoted_string_buffer); else print_error("Warning: This entry is pretty silly", np->label, type); } else { - print_error("No end to oid", (char *)NULL, type); + print_error("No end to oid", (char *) NULL, type); free_node(np); np = 0; } /* free oid array */ - for(count = 0; count < length; count++){ + for (count = 0; count < length; count++) { if (oid[count].label) free(oid[count].label); oid[count].label = 0; @@ -1292,8 +1292,8 @@ printf("Description== \"%.50s\"\n", quoted_string_buffer); */ static struct node * parse_compliance(fp, name) - FILE *fp; - char *name; + FILE *fp; + char *name; { int type; char token[MAXTOKEN]; @@ -1301,17 +1301,17 @@ parse_compliance(fp, name) struct subid oid[32]; struct node *np; - np = (struct node *)Malloc(sizeof(struct node)); + np = (struct node *) Malloc(sizeof(struct node)); np->type = 0; np->next = 0; np->enums = 0; - np->description = NULL; /* default to an empty description */ + np->description = NULL; /* default to an empty description */ type = get_token(fp, token); while (type != EQUALS) { type = get_token(fp, token); } length = getoid(fp, oid, 32); - if (length > 1 && length <= 32){ + if (length > 1 && length <= 32) { /* just take the last pair in the oid list */ if (oid[length - 2].label) strncpy(np->parent, oid[length - 2].label, MAXLABEL); @@ -1321,12 +1321,12 @@ parse_compliance(fp, name) else print_error("Warning: This entry is pretty silly", np->label, type); } else { - print_error("No end to oid", (char *)NULL, type); + print_error("No end to oid", (char *) NULL, type); free_node(np); np = 0; } /* free oid array */ - for(count = 0; count < length; count++){ + for (count = 0; count < length; count++) { if (oid[count].label) free(oid[count].label); oid[count].label = 0; @@ -1342,8 +1342,8 @@ parse_compliance(fp, name) */ static struct node * parse_moduleIdentity(fp, name) - FILE *fp; - char *name; + FILE *fp; + char *name; { int type; char token[MAXTOKEN]; @@ -1351,17 +1351,17 @@ parse_moduleIdentity(fp, name) struct subid oid[32]; struct node *np; - np = (struct node *)Malloc(sizeof(struct node)); + np = (struct node *) Malloc(sizeof(struct node)); np->type = 0; np->next = 0; np->enums = 0; - np->description = NULL; /* default to an empty description */ + np->description = NULL; /* default to an empty description */ type = get_token(fp, token); while (type != EQUALS) { type = get_token(fp, token); } length = getoid(fp, oid, 32); - if (length > 1 && length <= 32){ + if (length > 1 && length <= 32) { /* just take the last pair in the oid list */ if (oid[length - 2].label) strncpy(np->parent, oid[length - 2].label, MAXLABEL); @@ -1371,12 +1371,12 @@ parse_moduleIdentity(fp, name) else print_error("Warning: This entry is pretty silly", np->label, type); } else { - print_error("No end to oid", (char *)NULL, type); + print_error("No end to oid", (char *) NULL, type); free_node(np); np = 0; } /* free oid array */ - for(count = 0; count < length; count++){ + for (count = 0; count < length; count++) { if (oid[count].label) free(oid[count].label); oid[count].label = 0; @@ -1384,21 +1384,22 @@ parse_moduleIdentity(fp, name) return np; } -int parse_mib_header(fp, name) - FILE *fp; - char *name; +int +parse_mib_header(fp, name) + FILE *fp; + char *name; { int type = DEFINITIONS; char token[MAXTOKEN]; - + /* This probably isn't good enough. If there is no - imports clause we can't go around waiting (forever) for a semicolon. - We need to check for semi following an EXPORTS clause or an IMPORTS - clause of both. Look for BEGIN; in my initial MIBs to see those - that I needed to hack to get to parse because they didn't have - an IMPORTS or and EXPORTS clause. - */ - while(type != SEMI && type != ENDOFFILE){ + * imports clause we can't go around waiting (forever) for a semicolon. + * We need to check for semi following an EXPORTS clause or an IMPORTS + * clause of both. Look for BEGIN; in my initial MIBs to see those + * that I needed to hack to get to parse because they didn't have + * an IMPORTS or and EXPORTS clause. + */ + while (type != SEMI && type != ENDOFFILE) { type = get_token(fp, token); } return (type == SEMI); @@ -1412,32 +1413,32 @@ int parse_mib_header(fp, name) */ static struct node * parse(fp) - FILE *fp; + FILE *fp; { char token[MAXTOKEN]; char name[MAXTOKEN]; - int type = 1; + int type = 1; #define BETWEEN_MIBS 1 #define IN_MIB 2 int state = BETWEEN_MIBS; struct node *np = 0, *root = NULL; hash_init(); - quoted_string_buffer = (char *)calloc(1, MAXQUOTESTR); /* free this later */ + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); /* free this later */ bzero(tclist, 64 * sizeof(struct tc)); - while(type != ENDOFFILE){ + while (type != ENDOFFILE) { type = get_token(fp, token); -skipget: - if (type == END){ - if (state != IN_MIB){ - print_error("Error, end before start of MIB.", (char *)NULL, type); + skipget: + if (type == END) { + if (state != IN_MIB) { + print_error("Error, end before start of MIB.", (char *) NULL, type); return NULL; } state = BETWEEN_MIBS; continue; - } else if (type != LABEL){ - if (type == ENDOFFILE){ + } else if (type != LABEL) { + if (type == ENDOFFILE) { return root; } print_error(token, "is a reserved word", type); @@ -1445,163 +1446,163 @@ skipget: } strncpy(name, token, MAXTOKEN); type = get_token(fp, token); - if (type == DEFINITIONS){ - if (state != BETWEEN_MIBS){ - print_error("Error, nested MIBS.", (char *)NULL, type); + if (type == DEFINITIONS) { + if (state != BETWEEN_MIBS) { + print_error("Error, nested MIBS.", (char *) NULL, type); return NULL; } state = IN_MIB; - if (!parse_mib_header(fp, name)){ - print_error("Bad parse of module header", (char *)NULL, type); + if (!parse_mib_header(fp, name)) { + print_error("Bad parse of module header", (char *) NULL, type); return NULL; } - } else if (type == OBJTYPE){ - if (root == NULL){ + } else if (type == OBJTYPE) { + if (root == NULL) { /* first link in chain */ np = root = parse_objecttype(fp, name); - if (np == NULL){ - print_error("Bad parse of object type", (char *)NULL, - type); + if (np == NULL) { + print_error("Bad parse of object type", (char *) NULL, + type); return NULL; } } else { np->next = parse_objecttype(fp, name); - if (np->next == NULL){ - print_error("Bad parse of objecttype", (char *)NULL, - type); + if (np->next == NULL) { + print_error("Bad parse of objecttype", (char *) NULL, + type); return NULL; } } /* now find end of chain */ - while(np->next) + while (np->next) np = np->next; - } else if (type == OBJGROUP){ - if (root == NULL){ + } else if (type == OBJGROUP) { + if (root == NULL) { /* first link in chain */ np = root = parse_objectgroup(fp, name); - if (np == NULL){ - print_error("Bad parse of object group", (char *)NULL, - type); + if (np == NULL) { + print_error("Bad parse of object group", (char *) NULL, + type); return NULL; } } else { np->next = parse_objectgroup(fp, name); - if (np->next == NULL){ - print_error("Bad parse of objectgroup", (char *)NULL, - type); + if (np->next == NULL) { + print_error("Bad parse of objectgroup", (char *) NULL, + type); return NULL; } } /* now find end of chain */ - while(np->next) + while (np->next) np = np->next; - } else if (type == NOTIFTYPE){ - if (root == NULL){ + } else if (type == NOTIFTYPE) { + if (root == NULL) { /* first link in chain */ np = root = parse_notificationDefinition(fp, name); - if (np == NULL){ + if (np == NULL) { print_error("Bad parse of notification definition", - (char *)NULL, type); + (char *) NULL, type); return NULL; } } else { np->next = parse_notificationDefinition(fp, name); - if (np->next == NULL){ + if (np->next == NULL) { print_error("Bad parse of notification definition", - (char *)NULL, type); + (char *) NULL, type); return NULL; } } /* now find end of chain */ - while(np->next) + while (np->next) np = np->next; - } else if (type == COMPLIANCE){ - if (root == NULL){ + } else if (type == COMPLIANCE) { + if (root == NULL) { /* first link in chain */ np = root = parse_compliance(fp, name); - if (np == NULL){ - print_error("Bad parse of module compliance", (char *)NULL, - type); + if (np == NULL) { + print_error("Bad parse of module compliance", (char *) NULL, + type); return NULL; } } else { np->next = parse_compliance(fp, name); - if (np->next == NULL){ - print_error("Bad parse of module compliance", (char *)NULL, - type); + if (np->next == NULL) { + print_error("Bad parse of module compliance", (char *) NULL, + type); return NULL; } } /* now find end of chain */ - while(np->next) + while (np->next) np = np->next; - } else if (type == MODULEIDENTITY){ - if (root == NULL){ + } else if (type == MODULEIDENTITY) { + if (root == NULL) { /* first link in chain */ np = root = parse_moduleIdentity(fp, name); - if (np == NULL){ - print_error("Bad parse of module identity", (char *)NULL, - type); + if (np == NULL) { + print_error("Bad parse of module identity", (char *) NULL, + type); return NULL; } } else { np->next = parse_moduleIdentity(fp, name); - if (np->next == NULL){ - print_error("Bad parse of module identity", (char *)NULL, - type); + if (np->next == NULL) { + print_error("Bad parse of module identity", (char *) NULL, + type); return NULL; } } /* now find end of chain */ - while(np->next) + while (np->next) np = np->next; - } else if (type == OBJID){ - if (root == NULL){ + } else if (type == OBJID) { + if (root == NULL) { /* first link in chain */ np = root = parse_objectid(fp, name); - if (np == NULL){ - print_error("Bad parse of object id", (char *)NULL, type); + if (np == NULL) { + print_error("Bad parse of object id", (char *) NULL, type); return NULL; } } else { np->next = parse_objectid(fp, name); - if (np->next == NULL){ - print_error("Bad parse of object type", (char *)NULL, - type); + if (np->next == NULL) { + print_error("Bad parse of object type", (char *) NULL, + type); return NULL; } } /* now find end of chain */ - while(np->next) + while (np->next) np = np->next; - } else if (type == EQUALS){ - if (!parse_asntype(fp, name, &type, token)){ + } else if (type == EQUALS) { + if (!parse_asntype(fp, name, &type, token)) { print_error("Bad parse of ASN type definition.", NULL, EQUALS); return NULL; } goto skipget; - } else if (type == ENDOFFILE){ + } else if (type == ENDOFFILE) { break; } else { - print_error("Bad operator", (char *)NULL, type); + print_error("Bad operator", (char *) NULL, type); return NULL; } } #ifdef TEST -{ - struct enum_list *ep; - - for(np = root; np; np = np->next){ - printf("%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid, + { + struct enum_list *ep; + + for (np = root; np; np = np->next) { + printf("%s ::= { %s %d } (%d)\n", np->label, np->parent, np->subid, np->type); - if (np->enums){ - printf("Enums: \n"); - for(ep = np->enums; ep; ep = ep->next){ - printf("%s(%d)\n", ep->label, ep->value); + if (np->enums) { + printf("Enums: \n"); + for (ep = np->enums; ep; ep = ep->next) { + printf("%s(%d)\n", ep->label, ep->value); + } } } } -} #endif /* TEST */ return root; } @@ -1612,8 +1613,8 @@ skipget: */ static int get_token(fp, token) - FILE *fp; - char *token; + FILE *fp; + char *token; { static char last = ' '; int ch; @@ -1624,7 +1625,7 @@ get_token(fp, token) *cp = 0; ch = last; /* skip all white space */ - while(isspace(ch) && ch != -1){ + while (isspace(ch) && ch != -1) { ch = getc(fp); if (ch == '\n') Line++; @@ -1634,7 +1635,6 @@ get_token(fp, token) } else if (ch == '"') { return parseQuoteString(fp, token); } - /* * Accumulate characters until end of token is found. Then attempt to * match this token as a reserved word. If a match is found, return the @@ -1644,8 +1644,8 @@ get_token(fp, token) if (ch == '\n') Line++; if (isspace(ch) || ch == '(' || ch == ')' || ch == '{' || ch == '}' || - ch == ',' || ch == ';'){ - if (!isspace(ch) && *token == 0){ + ch == ',' || ch == ';') { + if (!isspace(ch) && *token == 0) { hash += ch; *cp++ = ch; last = ' '; @@ -1656,19 +1656,18 @@ get_token(fp, token) for (tp = buckets[BUCKET(hash)]; tp; tp = tp->next) { if ((tp->hash == hash) && (strcmp(tp->name, token) == 0)) - break; + break; } - if (tp){ + if (tp) { if (tp->token == CONTINUE) continue; return (tp->token); } - - if (token[0] == '-' && token[1] == '-'){ + if (token[0] == '-' && token[1] == '-') { /* strip comment */ - if (ch != '\n'){ + if (ch != '\n') { while ((ch = getc(fp)) != -1) - if (ch == '\n'){ + if (ch == '\n') { Line++; break; } @@ -1676,9 +1675,9 @@ get_token(fp, token) if (ch == -1) return ENDOFFILE; last = ch; - return get_token(fp, token); + return get_token(fp, token); } - for(cp = token; *cp; cp++) + for (cp = token; *cp; cp++) if (!isdigit(*cp)) return LABEL; return NUMBER; @@ -1688,14 +1687,14 @@ get_token(fp, token) if (ch == '\n') Line++; } - + } while ((ch = getc(fp)) != -1); return ENDOFFILE; } struct tree * read_mib(filename) - char *filename; + char *filename; { FILE *fp; struct node *nodes; @@ -1705,7 +1704,7 @@ read_mib(filename) if (fp == NULL) return NULL; nodes = parse(fp); - if (!nodes){ + if (!nodes) { fprintf(stderr, "Mib table is bad. Exiting\n"); exit(1); } @@ -1717,15 +1716,15 @@ read_mib(filename) #ifdef TEST main(argc, argv) - int argc; - char *argv[]; + int argc; + char *argv[]; { FILE *fp; struct node *nodes; struct tree *tp; fp = fopen("mib.txt", "r"); - if (fp == NULL){ + if (fp == NULL) { fprintf(stderr, "open failed\n"); return 1; } @@ -1739,22 +1738,21 @@ main(argc, argv) static int parseQuoteString(fp, token) - FILE *fp; - char *token; + FILE *fp; + char *token; { int ch; ch = ' '; - *token = '\0'; /* make the token empty */ + *token = '\0'; /* make the token empty */ - while(ch != -1) { - ch = getc(fp); + while (ch != -1) { + ch = getc(fp); if (ch == '\n') Line++; else if (ch == '"') { - return QUOTESTRING; - } - + return QUOTESTRING; + } } return 0; @@ -1766,30 +1764,30 @@ parseQuoteString(fp, token) */ static int tossObjectIdentifier(fp) - FILE *fp; + FILE *fp; { int ch; - ch = getc(fp); + ch = getc(fp); /* ch = last; = ' '? */ /* skip all white space */ - while(isspace(ch) && ch != -1){ - ch = getc(fp); - if (ch == '\n') - Line++; + while (isspace(ch) && ch != -1) { + ch = getc(fp); + if (ch == '\n') + Line++; } if (ch != '{') - return 0; + return 0; - while(ch != -1) { - ch = getc(fp); + while (ch != -1) { + ch = getc(fp); - if (ch == '\n') - Line++; - else if (ch == '}') - return OBJID; + if (ch == '\n') + Line++; + else if (ch == '}') + return OBJID; } -/* last = ch;*/ +/* last = ch; */ return 0; } diff --git a/snmplib/snmp_api.c b/snmplib/snmp_api.c index 65646b1c7f..187a9ff927 100644 --- a/snmplib/snmp_api.c +++ b/snmplib/snmp_api.c @@ -1,3 +1,5 @@ + + /*********************************************************** Copyright 1989 by Carnegie Mellon University @@ -11,6 +13,20428 @@ supporting documentation, and that the name of CMU not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = +{1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests; /* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = +{ + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR) { + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp() +{ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *) 0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} + +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if (length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int) (packet[count] & 255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid = 0, retries = 1; + if (rp) { + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch (code) { + case TRACE_SEND: + printf("send pdu (%d)", retries); + break; + case TRACE_RECV: + printf("recv pdu"); + break; + case TRACE_TIMEOUT: + printf("time out"); + break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *) calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *) calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *) isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *) calloc(1, sizeof(struct snmp_session)); + bcopy((char *) session, (char *) slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL) { + cp = (u_char *) calloc(1, (unsigned) strlen(session->peername) + 1); + strcpy((char *) cp, session->peername); + session->peername = (char *) cp; + } + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN) { + if (*session->community == '+') { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community + 1, (char *) cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) DEFAULT_COMMUNITY, (char *) cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0) { + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)) { + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME) { + if ((addr = inet_addr(session->peername)) != -1) { + bcopy((char *) &addr, (char *) &isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL) { + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)) { + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *) hp->h_addr, (char *) &isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT) { + /*servp = getservbyname("snmp", "udp"); */ + servp = NULL; + if (servp != NULL) { + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *) &me, sizeof(me)) != 0) { + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (!snmp_close(session)) { + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + if (*cp == '/') { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string(session); + session->qoS |= USEC_QOS_GENREPORT; + } + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent(session) + struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy(session->userName, "public"); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS) { + memcpy(session->agentID, response->params.agentID, 12); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT) { + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit(-1); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1/***/ BUG_SNMPTRACE */cked for testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ + +/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = +{1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests; /* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = +{ + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR) { + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp() +{ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *) 0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} + +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if (length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int) (packet[count] & 255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid = 0, retries = 1; + if (rp) { + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch (code) { + case TRACE_SEND: + printf("send pdu (%d)", retries); + break; + case TRACE_RECV: + printf("recv pdu"); + break; + case TRACE_TIMEOUT: + printf("time out"); + break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *) calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *) calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *) isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *) calloc(1, sizeof(struct snmp_session)); + bcopy((char *) session, (char *) slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL) { + cp = (u_char *) calloc(1, (unsigned) strlen(session->peername) + 1); + strcpy((char *) cp, session->peername); + session->peername = (char *) cp; + } + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN) { + if (*session->community == '+') { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community + 1, (char *) cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) DEFAULT_COMMUNITY, (char *) cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0) { + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)) { + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME) { + if ((addr = inet_addr(session->peername)) != -1) { + bcopy((char *) &addr, (char *) &isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL) { + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)) { + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *) hp->h_addr, (char *) &isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT) { + /*servp = getservbyname("snmp", "udp"); */ + servp = NULL; + if (servp != NULL) { + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *) &me, sizeof(me)) != 0) { + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (!snmp_close(session)) { + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + if (*cp == '/') { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string(session); + session->qoS |= USEC_QOS_GENREPORT; + } + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent(session) + struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy(session->userName, "public"); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS) { + memcpy(session->agentID, response->params.agentID, 12); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT) { + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit(-1); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +ring(fp, token) + FILE *fp; + char *token; +{ + int ch; + + ch = ' '; + *token = '\0'; /* make the token empty */ + + while (ch != -1) { + ch = getc(fp); + if (ch == '\n') + Line++; + else if (ch == '"') { + return QUOTESTRING; + } + } + + return 0; +} + +/* + * This routine parses a string like { blah blah blah } and returns OBJID if + * it is well formed, and NULL if not. + */ +static int +tossObjectIdentifier(fp) + FILE *fp; +{ + int ch; + + ch = getc(fp); +/* ch = last; = ' '? */ + /* skip all white space */ + while (isspace(ch) && ch != -1) { + ch = getc(fp); + if (ch == '\n') + Line++; + } + if (ch != '{') + return 0; + + while (ch != -1) { + ch = getc(fp); + + if (ch == '\n') + Line++; + else if (ch == '}') + return OBJID; + } + +/* last = ch; */ + return 0; +} +rn 0; + } + /* + * Optional parts of the OBJECT-TYPE macro + */ + type = get_token(fp, token); + while (type != EQUALS) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } +#ifdef TEST + printf("Description== \"%.50s\"\n", quoted_string_buffer); +#endif + np->description = quoted_string_buffer; + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); + break; + + case REFERENCE: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } + break; + case INDEX: + case DEFVAL: + case AUGMENTS: + case NUM_ENTRIES: + if (tossObjectIdentifier(fp) != OBJID) { + print_error("Bad Object Identifier", token, type); + free_node(np); + return 0; + } + break; + + default: + print_error("Bad format of optional clauses", token, type); + free_node(np); + return 0; + + } + type = get_token(fp, token); + } + if (type != EQUALS) { + print_error("Bad format", token, type); + free_node(np); + return 0; + } + length = getoid(fp, oid, 32); + if (length > 1 && length <= 32) { + /* just take the last pair in the oid list */ + if (oid[length - 2].label) + strncpy(np->parent, oid[length - 2].label, MAXLABEL); + strcpy(np->label, name); + if (oid[length - 1].subid != -1) + np->subid = oid[length - 1].subid; + else + print_error("Warning: This entry is pretty silly", np->label, type); + } else { + print_error("No end to oid", (char *) NULL, type); + free_node(np); + np = 0; + } + /* free oid array */ + for (count = 0; count < length; count++) { + if (oid[count].label) + free(oid[count].label); + oid[count].label = 0; + } + return np; +} + + +/* + * Parses an OBJECT GROUP macro. + * Returns 0 on error. + */ +static struct node * +parse_objectgroup(fp, name) + FILE *fp; + char *name; +{ + int type; + char token[MAXTOKEN]; + int count, length; + struct subid oid[32]; + struct node *np; + + np = (struct node *) Malloc(sizeof(struct node)); + np->type = 0; + np->next = 0; + np->enums = 0; + np->description = NULL; /* default to an empty description */ + type = get_token(fp, token); + while (type != EQUALS) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } +#ifdef TEST + printf("Description== \"%.50s\"\n", quoted_string_buffer); +#endif + np->description = quoted_string_buffer; + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); + break; + + default: + /* NOTHING */ + break; + } + type = get_token(fp, token); + } + length = getoid(fp, oid, 32); + if (length > 1 && length <= 32) { + /* just take the last pair in the oid list */ + if (oid[length - 2].label) + strncpy(np->parent, oid[length - 2].label, MAXLABEL); + strcpy(np->label, name); + if (oid[length - 1].subid != -1) + np->subid = oid[length - 1].subid; + else + print_error("Warning: This entry is pretty silly", np->label, type); + } else { + print_error("No end to oid", (char *) NULL, type); + free_node(np); + np = 0; + } + /* free oid array */ + for (count = 0; count < length; count++) { + if (oid[count].label) + free(oid[count].label); + oid[count].label = 0; + } + return np; +} + +/* + * Parses a NOTIFICATION-TYPE macro. + * Returns 0 on error. + */ +static struct node * +parse_notificationDefinition(fp, name) + FILE *fp; + char *name; +{ + int type; + char token[MAXTOKEN]; + int count, length; + struct subid oid[32]; + struct node *np; + + np = (struct node *) Malloc(sizeof(struct node)); + np->type = 0; + np->next = 0; + np->enums = 0; + np->description = NULL; /* default to an empty description */ + type = get_token(fp, token); + while (type != EQUALS) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } +#ifdef TEST + printf("Description== \"%.50s\"\n", quoted_string_buffer); +#endif + np->description = quoted_string_buffer; + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); + break; + + default: + /BÐ+= m +È /* */ B4¨NMPT^h */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if (!orp) + return; + if (isp->requests == orp) { + isp->requests = orp->next_request; /* unlink head */ + } else { + for (rp = isp->requests; rp; rp = rp->next_request) { + if (rp->next_request == orp) { + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL) { + snmp_free_pdu(orp->pdu); + } + free((char *) orp); +} + +#endif/***/ BUG_SNMPTRACE */cked for testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ùÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ °>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if (!orp) + return; + if (isp->requests == orp) { + isp->requests = orp->next_request; /* unlink head */ + } else { + for (rp = isp->requests; rp; rp = rp->next_request) { + if (rp->next_request == orp) { + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL) { + snmp_free_pdu(orp->pdu); + } + free((char *) orp); +} + oid list */ + if (oid[length - 2].label) + strncpy(np->parent, oid[length - 2].label, MAXLABEL); + strcpy(np->label, name); + if (oid[length - 1].subid != -1) + np->subid = oid[length - 1].subid; + else + print_error("Warning: This entry is pretty silly", np->label, type); + } else { + print_error("No end to oid", (char *) NULL, type); + free_node(np); + np = 0; + } + /* free oid array */ + for (count = 0; count < length; count++) { + if (oid[count].label) + free(oid[count].label); + oid[count].label = 0; + } + return np; +} + +/* + * Parses a NOTIFICATION-TYPE macro. + * Returns 0 on error. + */ +static struct node * +parse_notificationDefinition(fp, name) + FILE *fp; + char *name; +{ + int type; + char token[MAXTOKEN]; + int count, length; + struct subid oid[32]; + struct node *np; + + np = (struct node *) Malloc(sizeof(struct node)); + np->type = 0; + np->next = 0; + np->enums = 0; + np->description = NULL; /* default to an empty description */ + type = get_token(fp, token); + while (type != EQUALS) { + switch (type) { + case DESCRIPTION: + type = get_token(fp, token); + if (type != QUOTESTRING) { + print_error("Bad DESCRIPTION", token, type); + free_node(np); + return 0; + } +#ifdef TEST + printf("Description== \"%.50s\"\n", quoted_string_buffer); +#endif + np->description = quoted_string_buffer; + quoted_string_buffer = (char *) calloc(1, MAXQUOTESTR); + break; + + default: + /BÐ+= m +È /* */ B4¨NMPT^h */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·qBÐ+= m +È /* */ B4¨NMPT—X */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while (rp) { + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *) orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session) { /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for (slp = Sessions; slp; slp = slp->next) { + if (slp->session == session) { + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp) { + if (slp->session->community != NULL) + free((char *) slp->session->community); + if (slp->session->peername != NULL) + free((char *) slp->session->peername); + free((char *) slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *) slp->internal); + free((char *) slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for (vp = pdu->variables; vp; vp = vp->next_variable) { + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *) vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *) packet, (char *) cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG) { + /* request id */ + cp = asn_build_int(packet, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *) pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char) IPADDRESS, + (u_char *) & pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char) TIMETICKS, + (long *) &pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *) buf, (char *) cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char) pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *) packet, (char *) cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build(packet, &length, session, is_agent, totallength); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *) buf, (char *) cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if (session->qoS & USEC_QOS_AUTH) + md5Digest(packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16)); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if (version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if (session->authenticator) { + ret = session->authenticator(origdata, origlength, save_data - community_length, + community_length, session, pdu); + if (ret < 0) + return ret; + } + if (pdu->command != TRP_REQ_MSG) { + data = asn_parse_int(data, &length, &type, (long *) &pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *) calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *) objid, (char *) pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *) & pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while ((int) length > 0) { + if (pdu->variables == NULL) { + pdu->variables = vp = (struct variable_list *) calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *) calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *) &length); + if (data == NULL) + return -1; + op = (oid *) calloc(1, (unsigned) vp->name_length * sizeof(oid)); + bcopy((char *) objid, (char *) op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch ((short) vp->type) { + case ASN_INTEGER: + vp->val.integer = (long *) calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *) vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *) calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *) vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *) calloc(1, sizeof(struct counter64)); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *) vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *) calloc(1, (unsigned) vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *) calloc(1, (unsigned) vp->val_len); + bcopy((char *) objid, (char *) vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for (slp = Sessions; slp; slp = slp->next) { + if (slp->session == session) { + isp = slp->internal; + break; + } + } + + if (!pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (isp == NULL) { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG) { + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH) { + pdu->enterprise = (oid *) calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *) DEFAULT_ENTERPRISE, (char *) pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE) / sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS) { + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS) { + bcopy((char *) &isp->addr, (char *) &pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + if (snmp_build(session, pdu, packet, &length, 0) < 0) { + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1/***/ if we found entry that points here */ + oslp e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù‚àÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *) pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char) IPADDRESS, + (u_char *) & pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char) TIMETICKS, + (long *) &pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *) buf, (char *) cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char) pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *) packet, (char *) cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build(packet, &length, session, is_agent, totallength); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *) buf, (char *) cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if (session->qoS & USEC_QOS_AUTH) + md5Digest(packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16)); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if (version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if (session->authenticator) { + ret = session->authenticator(origdata, origlength, save_data - community_length, + community_length, session, pdu); + if (ret < 0) + return ret; + } + if (pdu->command != TRP_REQ_MSG) { + data = asn_parse_int(data, &length, &type, (long *) &pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *) calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *) objid, (char *) pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *) & pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *) &pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while ((int) length > 0) { + if (pdu->variables == NULL) { + pdu->variables = vp = (struct variable_list *) calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *) calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *) &length); + if (data == NULL) + return -1; + op = (oid *) calloc(1, (unsigned) vp->name_length * sizeof(oid)); + bcopy((char *) objid, (char *) op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch ((short) vp->type) { + case ASN_INTEGER: + vp->val.integer = (long *) calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *) vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *) calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *) vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *) calloc(1, sizeof(struct counter64)); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *) vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *) calloc(1, (unsigned) vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *) calloc(1, (unsigned) vp->val_len); + bcopy((char *) objid, (char *) vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for (slp = Sessions; slp; slp = slp->next) { + if (slp->session == session) { + isp = slp->internal; + break; + } + } + + if (!pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (isp == NULL) { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG) { + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH) { + pdu->enterprise = (oid *) calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *) DEFAULT_ENTERPRISE, (char *) pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE) / sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS) { + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS) { + bcopy((char *) &isp->addr, (char *) &pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + if (snmp_build(session, pdu, packet, &length, 0) < 0) { + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while (rp) { + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *) orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session) { /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for (slp = Sessions; slp; slp = slp->next) { + if (slp->session == session) { + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp) { + if (slp->session->community != NULL) + free((char *) slp->session->community); + if (slp->session->peername != NULL) + free((char *) slp->session->peername); + free((char *) slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *) slp->internal); + free((char *) slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for (vp = pdu->variables; vp; vp = vp->next_variable) { + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *) vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *) packet, (char *) cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG) { + /* request id */ + cp = asn_build_int(packet, &length, + (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *) &pdu->BÐ+= m +È /* >X*/ B4¨NMPT˜à */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet) { + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif/***/ if we found entry that points here */ + oslp e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ‚àÿ¶·ÿ¶Ù4¨ÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet) { + snmp_print_packet(packet, length, pdu->address, 1); + } +MUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + structBÐ+= m +È /* */ B>XNMPTÊ */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *) 0); + if (sendto(isp->sd, (char *) packet, length, 0, (struct sockaddr *) &pdu->address, sizeof(pdu->address)) < 0) { + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG) { + /* set up to expect a response */ + rp = (struct request_list *) calloc(1, sizeof(struct request_list)); +#if 1/***/ if we found entry that points here */ + oslp e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù4¨ÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ ables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *) 0); + if (sendto(isp->sd, (char *) packet, length, 0, (struct sockaddr *) &pdu->address, sizeof(pdu->address)) < 0) { + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG) { + /* set up to expect a response */ + rp = (struct request_list *) calloc(1, sizeof(struct request_list)); +ar *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variBÐ+= m +È /* 4¨*/ BNMPTÊ */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if (!rp) { + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif/***/ if we found entry that points here */ + oslp e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù‚àÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ e SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if (!rp) { + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +ULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + casBÐ+= m +È /* >X*/ B4¨NMPT˰ */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu *pdu) +{ + struct variable_list *vp, *ovp; + + if (!pdu) + return; + + vp = pdu->variables; + while (vp) { + if (vp->name) { + free((char *) vp->name); + } + if (vp->val.string) { + free((char *) vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *) ovp); + } + if (pdu->enterprise) { + free((char *) pdu->enterprise); + } + free((char *) pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for (slp = Sessions; slp; slp = slp->next) { + if (FD_ISSET(slp->internal->sd, fdset)) { + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *) packet, PACKET_LENGTH, 0, (struct sockaddr *) &from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1/***/ if we found entry that points here */ + oslp e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù4¨ÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu *pdu) +{ + struct variable_list *vp, *ovp; + + if (!pdu) + return; + + vp = pdu->variables; + while (vp) { + if (vp->name) { + free((char *) vp->name); + } + if (vp->val.string) { + free((char *) vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *) ovp); + } + if (pdu->enterprise) { + free((char *) pdu->enterprise); + } + free((char *) pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for (slp = Sessions; slp; slp = slp->next) { + if (FD_ISSET(slp->internal->sd, fdset)) { + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *) packet, PACKET_LENGTH, 0, (struct sockaddr *) &from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +ponse->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid);BÐ+= m +È /* 4¨*/ BNMPTÍ8 */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet) { + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *) calloc(1, sizeof(struct snmp_pdu)); + + if (!pdu) { + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif/***/ if we found entry that points here */ + oslp e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ‚àÿ¶·ÿ¶Ù4¨ÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet) { + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *) calloc(1, sizeof(struct snmp_pdu)); + + if (!pdu) { + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } + == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + BÐ+= m +È /* */ B>XNMPTÔè */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0) { + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG) { +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next = 0; + for (rp = isp->requests; rp; rp = rp_next) { + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid) { +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1) { + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif/***/ g fix: illegal re-use of rp killed some requests */ replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù‚àÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0) { + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG) { +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next = 0; + for (rp = isp->requests; rp; rp = rp_next) { + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid) { +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1) { + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +>pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)BÐ+= m +È /* >X*/ B7NMPTÔè */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG) { +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for (slp = Sessions; slp; slp = slp->next) { + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests) { + /* found another session with outstanding requests */ + requests++; + for (rp = isp->requests; rp; rp = rp->next_request) { + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *) 0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L) { + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0) { + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)) { + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next */ + struct request_list *rp, *rp_next = 0; +#endif/***/ placing freeme by simpler and safer rp_next*/n s */ replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù0¸ÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG) { +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for (slp = Sessions; slp; slp = slp->next) { + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests) { + /* found another session with outstanding requests */ + requests++; + for (rp = isp->requests; rp; rp = rp->next_request) { + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *) 0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L) { + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0) { + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)) { + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next */ + struct request_list *rp, *rp_next = 0; + */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unlessBÐ+= m +È /* 0¸*/ BNMPTو */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *) 0); + /* + * For each request outstanding, check to see if it has expired. + */ + for (slp = Sessions; slp; slp = slp->next) { + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for (rp = isp->requests; rp; rp = rp_next) { + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)) { + /* this timer has expired */ + if (rp->retries >= sp->retries) { +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +#endif/***/ mplification */by simpler and safer rp_next*/n s */ replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù‚àÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ h) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *) 0); + /* + * For each request outstanding, check to see if it has expired. + */ + for (slp = Sessions; slp; slp = slp->next) { + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for (rp = isp->requests; rp; rp = rp_next) { + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)) { + /* this timer has expired */ + if (rp->retries >= sp->retries) { +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +r *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, lengtBÐ+= m +È /* >X*/ B3NMPTèè */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *)0); + /* + * For each request outstanding, check to see if it has expired. + */ + for(slp = Sessions; slp; slp = slp->next){ + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)){ + /* this timer has expired */ + if (rp->retries >= sp->retries){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +#endif /***/ + } else { + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct timeval tv; + + /* retransmit this pdu */ + rp->retries++; + rp->timeout <<= 1; + if (snmp_build(sp, rp->pdu, packet, &length, 0) < 0) { + fprintf(stderr, "Error building packet\n"); + } +#if 1/***/ mplification */by simpler and safer rp_next*/n s */ replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù‚àÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ ; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *)0); + /* + * For each request outstanding, check to see if it has expired. + */ + for(slp = Sessions; slp; slp = slp->next){ + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)){ + /* this timer has expired */ + if (rp->retries >= sp->retries){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +#endif /***/ + } else { + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct timeval tv; + + /* retransmit this pdu */ + rp->retries++; + rp->timeout <<= 1; + if (snmp_build(sp, rp->pdu, packet, &length, 0) < 0) { + fprintf(stderr, "Error building packet\n"); + } + the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + returnBÐ+= m +È /* >X*/ B4¨NMPTì */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *)0); + /* + * For each request outstanding, check to see if it has expired. + */ + for(slp = Sessions; slp; slp = slp->next){ + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)){ + /* this timer has expired */ + if (rp->retries >= sp->retries){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +#endif /***/ + } else { + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct timeval tv; + + /* retransmit this pdu */ + rp->retries++; + rp->timeout <<= 1; + if (snmp_build(sp, rp->pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + } +#if 1 /***/ + if (snmp_dump_packet) { + snmp_print_packet(packet, length, rp->pdu->address, 1); + } +#endif/***/ mplification */by simpler and safer rp_next*/n s */ replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ‚àÿ¶·ÿ¶Ù4¨ÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ 64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *)0); + /* + * For each request outstanding, check to see if it has expired. + */ + for(slp = Sessions; slp; slp = slp->next){ + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)){ + /* this timer has expired */ + if (rp->retries >= sp->retries){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +#endif /***/ + } else { + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct timeval tv; + + /* retransmit this pdu */ + rp->retries++; + rp->timeout <<= 1; + if (snmp_build(sp, rp->pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + } +#if 1 /***/ + if (snmp_dump_packet) { + snmp_print_packet(packet, length, rp->pdu->address, 1); + } + If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counterBÐ+= m +È /* */ B>XNMPTíˆ */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + +CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL +CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR +ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. +******************************************************************/ +/* + * snmp_api.c - API for access to snmp. + */ +#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */ +#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef linux +#include +#include +#include +#include +#endif + + +#include "asn1.h" +#include "snmp.h" +#include "snmp_impl.h" +#include "snmp_api.h" +#include "snmp_client.h" + +#define PACKET_LENGTH 4500 + +#ifndef BSD4_3 +#define BSD4_2 +#endif + +#if !defined(BSD4_3) && !defined(linux) && !defined(sun) + +typedef long fd_mask; +#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ + +#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS))) +#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS))) +#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS))) +#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p))) +#endif + +oid default_enterprise[] = {1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */ + +#define DEFAULT_COMMUNITY "public" +#define DEFAULT_REMPORT SNMP_PORT +#define DEFAULT_ENTERPRISE default_enterprise +#define DEFAULT_TIME 0 +#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */ + +/* + * Internal information about the state of the snmp session. + */ +struct snmp_internal_session { + int sd; /* socket descriptor for this connection */ + ipaddr addr; /* address of connected peer */ + struct request_list *requests;/* Info about outstanding requests */ +}; + +/* + * A list of all the outstanding requests for a particular session. + */ +struct request_list { + struct request_list *next_request; + u_long request_id; /* request id */ + int retries; /* Number of retries */ + u_long timeout; /* length to wait for timeout */ + struct timeval time; /* Time this request was made */ + struct timeval expire; /* time this request is due to expire */ + struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */ +}; + +/* + * The list of active/open sessions. + */ +struct session_list { + struct session_list *next; + struct snmp_session *session; + struct snmp_internal_session *internal; +}; + +struct session_list *Sessions = NULL; + +u_long Reqid = 0; +int snmp_errno = 0; + +char *api_errors[4] = { + "Unknown session", + "Unknown host", + "Invalid local port", + "Unknown Error" +}; + + +void sync_with_agent(); +int parse_app_community_string(); +void snmp_synch_setup(); +int snmp_synch_response(); +void md5Digest(); + + +static char * +api_errstring(snmp_errnumber) + int snmp_errnumber; +{ + if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR){ + return api_errors[snmp_errnumber + 4]; + } else { + return "Unknown Error"; + } +} + +#if 0 +/* + * Gets initial request ID for all transactions. + */ +static void +init_snmp(){ + struct timeval tv; + + gettimeofday(&tv, (struct timezone *)0); + srandom(tv.tv_sec ^ tv.tv_usec); + Reqid = random(); +} +#endif + + +/* + * Dump snmp packet to stdout: + */ +static void +snmp_print_packet(packet, length, addr, code) + char *packet; + int length; + ipaddr addr; + int code; +{ + if(length < 0) { + return; + } + if (code <= 0) { /* received */ + printf("\nReceived %4d bytes from ", length); + } + else { /* sending */ + printf("\nSending %4d bytes to ", length); + } + printf("%s:", inet_ntoa(addr.sin_addr)); +#if DEBUG_SNMPFULLDUMP + for (count = 0; count < length; count++) { + if ((count & 15) == 0) { + printf("\n "); + } + printf("%02X ", (int)(packet[count]&255)); + } +#endif + fflush(stdout); +} + +#if DEBUG_SNMPTRACE +/* + * Print request + */ +#define TRACE_SEND (0) +#define TRACE_RECV (1) +#define TRACE_TIMEOUT (2) +static void +snmp_print_trace(slp, rp, code) + struct session_list *slp; + struct request_list *rp; + int code; +{ + int reqid=0, retries=1; + if( rp ){ + reqid = rp->request_id; + retries = rp->retries; + } + printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid); + switch(code) + { + case TRACE_SEND: printf("send pdu (%d)", retries);break; + case TRACE_RECV: printf("recv pdu");break; + case TRACE_TIMEOUT: printf("time out");break; + } + fflush(stdout); +} +#endif /* DEBUG_SNMPTRACE */ + + + + +/* + * Sets up the session with the snmp_session information provided + * by the user. Then opens and binds the necessary UDP port. + * A handle to the created session is returned (this is different than + * the pointer passed to snmp_open()). On any error, NULL is returned + * and snmp_errno is set to the appropriate error code. + */ +struct snmp_session * +snmp_open(session) + struct snmp_session *session; +{ + struct session_list *slp; + struct snmp_internal_session *isp; + u_char *cp; + int sd; + u_long addr; + struct sockaddr_in me; + struct hostent *hp; + struct servent *servp; + extern int check_received_pkt(); + + /* Copy session structure and link into list */ + slp = (struct session_list *)calloc(1, sizeof(struct session_list)); + slp->internal = isp = (struct snmp_internal_session *)calloc(1, sizeof(struct snmp_internal_session)); + bzero((char *)isp, sizeof(struct snmp_internal_session)); + slp->internal->sd = -1; /* mark it not set */ + slp->session = (struct snmp_session *)calloc(1, sizeof(struct snmp_session)); + bcopy((char *)session, (char *)slp->session, sizeof(struct snmp_session)); + session = slp->session; + /* now link it in. */ + slp->next = Sessions; + Sessions = slp; + + /* + * session now points to the new structure that still contains pointers to + * data allocated elsewhere. Some of this data is copied to space malloc'd + * here, and the pointer replaced with the new one. + */ + + if (session->peername != NULL){ + cp = (u_char *)calloc(1, (unsigned)strlen(session->peername) + 1); + strcpy((char *)cp, session->peername); + session->peername = (char *)cp; + } + + if (session->retries == SNMP_DEFAULT_RETRIES) + session->retries = SNMP_API_DEFAULT_RETRIES; + if (session->timeout == SNMP_DEFAULT_TIMEOUT) + session->timeout = SNMP_API_DEFAULT_TIMEOUT; + if (session->MMS == 0 ) + session->MMS = DEFAULT_MMS; + isp->requests = NULL; + + + /* Fill in defaults if necessary */ + if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN){ + if( *session->community == '+' ) { + session->community_len--; + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community+1, (char *)cp, + session->community_len); + session->version = SNMP_VERSION_2C; + } else { + cp = (u_char *) calloc(1, (unsigned) session->community_len); + bcopy((char *) session->community, (char *) cp, + session->community_len); + } + + } else { + session->community_len = strlen(DEFAULT_COMMUNITY); + cp = (u_char *)calloc(1, (unsigned)session->community_len); + bcopy((char *)DEFAULT_COMMUNITY, (char *)cp, session->community_len); + } + + /* Set up connections */ + sd = socket(AF_INET, SOCK_DGRAM, 0); + if (sd < 0){ + perror("socket"); + snmp_errno = SNMPERR_GENERR; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(1); + } + return 0; + } + isp->sd = sd; + + if (session->peername != SNMP_DEFAULT_PEERNAME){ + if ((addr = inet_addr(session->peername)) != -1){ + bcopy((char *)&addr, (char *)&isp->addr.sin_addr, sizeof(isp->addr.sin_addr)); + } else { + hp = gethostbyname(session->peername); + if (hp == NULL){ + fprintf(stderr, "unknown host: %s\n", session->peername); + snmp_errno = SNMPERR_BAD_ADDRESS; + if (!snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno)); + exit(2); + } + return 0; + } else { + bcopy((char *)hp->h_addr, (char *)&isp->addr.sin_addr, hp->h_length); + } + } + isp->addr.sin_family = AF_INET; + if (session->remote_port == SNMP_DEFAULT_REMPORT){ + /*servp = getservbyname("snmp", "udp");*/ + servp=NULL; + if (servp != NULL){ + isp->addr.sin_port = servp->s_port; + } else { + isp->addr.sin_port = htons(SNMP_PORT); + } + } else { + isp->addr.sin_port = htons(session->remote_port); + } + } else { + isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS; + } + + me.sin_family = AF_INET; + me.sin_addr.s_addr = INADDR_ANY; + me.sin_port = htons(session->local_port); + if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){ + perror("bind"); + snmp_errno = SNMPERR_BAD_LOCPORT; + if (! snmp_close(session)){ + fprintf(stderr, "Couldn't abort session: %s. Exiting\n", + api_errstring(snmp_errno)); + exit(3); + } + return 0; + } + + if( *cp == '/' ) { + session->authenticator = check_received_pkt; + sync_with_agent(session); + parse_app_community_string( session ); + session->qoS |= USEC_QOS_GENREPORT; + } + + /* replace comm pointer with pointer to new data: */ + session->community = cp; + + return session; +} + +void +sync_with_agent( session ) +struct snmp_session *session; +{ + struct snmp_pdu *pdu, *response = 0; + int status; + + session->qoS = USEC_QOS_GENREPORT; + session->userLen = 6; + session->version = SNMP_VERSION_2; + strcpy( session->userName, "public" ); + + snmp_synch_setup(session); + pdu = snmp_pdu_create(GET_REQ_MSG); + status = snmp_synch_response(session, pdu, &response); + + if (status == STAT_SUCCESS){ + memcpy( session->agentID, response->params.agentID, 12 ); + + /* save the clocks -- even though they are not authentic */ + session->agentBoots = response->params.agentBoots; + session->agentTime = response->params.agentTime; + session->agentClock = response->params.agentTime - time(NULL); + + } else { + if (status == STAT_TIMEOUT){ + printf("No Response from %s\n", session->peername); + } else { /* status == STAT_ERROR */ + printf("An error occurred, Quitting\n"); + } + exit( -1 ); + } + + /** freed to early: + snmp_free_pdu(pdu); + if (response) snmp_free_pdu(response); + **/ +} +#if 1 /***/ +/* + * Unlink one element from input request list, + * then free it and it's pdu. + */ +static void +free_one_request(isp, orp) + struct snmp_internal_session *isp; + struct request_list *orp; +{ + struct request_list *rp; + if(! orp) return; + if(isp->requests == orp){ + isp->requests = orp->next_request; /* unlink head */ + } + else{ + for(rp = isp->requests; rp; rp = rp->next_request){ + if(rp->next_request == orp){ + rp->next_request = orp->next_request; /* unlink element */ + break; + } + } + } + if (orp->pdu != NULL){ + snmp_free_pdu(orp->pdu); + } + free((char *)orp); +} +#endif /***/ +/* + * Free each element in the input request list. + */ +static void +free_request_list(rp) + struct request_list *rp; +{ + struct request_list *orp; + + while(rp){ + orp = rp; + rp = rp->next_request; + if (orp->pdu != NULL) + snmp_free_pdu(orp->pdu); + free((char *)orp); + } +} + +/* + * Close the input session. Frees all data allocated for the session, + * dequeues any pending requests, and closes any sockets allocated for + * the session. Returns 0 on error, 1 otherwise. + */ +int +snmp_close(session) + struct snmp_session *session; +{ + struct session_list *slp = NULL, *oslp = NULL; + + if (Sessions->session == session){ /* If first entry */ + slp = Sessions; + Sessions = slp->next; + } else { + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + if (oslp) /* if we found entry that points here */ + oslp->next = slp->next; /* link around this entry */ + break; + } + oslp = slp; + } + } + /* If we found the session, free all data associated with it */ + if (slp){ + if (slp->session->community != NULL) + free((char *)slp->session->community); + if(slp->session->peername != NULL) + free((char *)slp->session->peername); + free((char *)slp->session); + if (slp->internal->sd != -1) + close(slp->internal->sd); + free_request_list(slp->internal->requests); + free((char *)slp->internal); + free((char *)slp); + } else { + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + return 1; +} + +/* + * Takes a session and a pdu and serializes the ASN PDU into the area + * pointed to by packet. out_length is the size of the data area available. + * Returns the length of the completed packet in out_length. If any errors + * occur, -1 is returned. If all goes well, 0 is returned. + */ +int +snmp_build(session, pdu, packet, out_length, is_agent) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *packet; + int *out_length; + int is_agent; +{ + u_char buf[PACKET_LENGTH]; + u_char *cp; + struct variable_list *vp; + int length; + int totallength; + + length = *out_length; + cp = packet; + for(vp = pdu->variables; vp; vp = vp->next_variable){ + cp = snmp_build_var_op(cp, vp->name, &vp->name_length, vp->type, vp->val_len, (u_char *)vp->val.string, &length); + if (cp == NULL) + return -1; + } + totallength = cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR), totallength); + if (cp == NULL) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + if (pdu->command != TRP_REQ_MSG){ + /* request id */ + cp = asn_build_int(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (cp == NULL) + return -1; + /* error status */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (cp == NULL) + return -1; + /* error index */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (cp == NULL) + return -1; + } else { /* this is a trap message */ + /* enterprise */ + cp = asn_build_objid(packet, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID), + (oid *)pdu->enterprise, pdu->enterprise_length); + if (cp == NULL) + return -1; + /* agent-addr */ + cp = asn_build_string(cp, &length, (u_char)IPADDRESS, + (u_char *)&pdu->agent_addr.sin_addr.s_addr, sizeof(pdu->agent_addr.sin_addr.s_addr)); + if (cp == NULL) + return -1; + /* generic trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (cp == NULL) + return -1; + /* specific trap */ + cp = asn_build_int(cp, &length, + (u_char)(ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_INTEGER), + (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (cp == NULL) + return -1; + /* timestamp */ + cp = asn_build_int(cp, &length, (u_char)TIMETICKS, + (long *)&pdu->time, sizeof(pdu->time)); + if (cp == NULL) + return -1; + } + if (length < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + + length = PACKET_LENGTH; + cp = asn_build_header(buf, &length, (u_char)pdu->command, totallength); + if (cp == NULL) + return -1; + if (length < totallength) + return -1; + bcopy((char *)packet, (char *)cp, totallength); + totallength += cp - buf; + + length = *out_length; + + cp = snmp_auth_build( packet, &length, session, is_agent, totallength ); + if (cp == NULL) + return -1; + if ((*out_length - (cp - packet)) < totallength) + return -1; + bcopy((char *)buf, (char *)cp, totallength); + totallength += cp - packet; + *out_length = totallength; + + if( session->qoS & USEC_QOS_AUTH ) + md5Digest( packet, totallength, cp - (session->contextLen + 16), + cp - (session->contextLen + 16) ); + + return 0; +} + +/* + * Parses the packet received on the input session, and places the data into + * the input pdu. length is the length of the input packet. If any errors + * are encountered, -1 is returned. Otherwise, a 0 is returned. + */ +static int +snmp_parse(session, pdu, data, length) + struct snmp_session *session; + struct snmp_pdu *pdu; + u_char *data; + int length; +{ + u_char msg_type; + u_char type; + u_char *var_val; + long version; + int len, four; + u_char community[256]; + int community_length = 256; + struct variable_list *vp = 0; + oid objid[MAX_NAME_LEN], *op; + u_char *origdata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *)0); + /* + * For each request outstanding, check to see if it has expired. + */ + for(slp = Sessions; slp; slp = slp->next){ + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)){ + /* this timer has expired */ + if (rp->retries >= sp->retries){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +#endif /***/ + } else { + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct timeval tv; + + /* retransmit this pdu */ + rp->retries++; + rp->timeout <<= 1; + if (snmp_build(sp, rp->pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, rp->pdu->address, 1); + } +#endif /***/ + gettimeofday(&tv, (struct timezone *) 0); + if (sendto(isp->sd, (char *) packet, length, 0, (struct sockaddr *) &rp->pdu->address, sizeof(rp->pdu->address)) < 0) { + perror("sendto"); + } + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + } +#if 1 /***/ /* simplification */ + } +#endif/***/ mplification */by simpler and safer rp_next*/n s */ replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿÿ¶·ÿ¶Ù‚àÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q@ 000000L; + earliest.tv_sec += 1; + } + if (earliest.tv_sec < 0){ + earliest.tv_sec = 0; + earliest.tv_usec = 0; + } + + /* if it was blocking before or our delta time is less, reset timeout */ + if (*block == 1 || timercmp(&earliest, timeout, <)){ + *timeout = earliest; + *block = 0; + } + return active; +} + +/* + * snmp_timeout should be called whenever the timeout from + * snmp_select_info expires, but it is idempotent, so snmp_timeout can + * be polled (probably a cpu expensive proposition). snmp_timeout + * checks to see if any of the sessions have an outstanding request + * that has timed out. If it finds one (or more), and that pdu has + * more retries available, a new packet is formed from the pdu and is + * resent. If there are no more retries available, the callback for + * the session is used to alert the user of the timeout. + */ +void +snmp_timeout() +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; +#if 1 /***/ /* replacing freeme by simpler and safer rp_next*/ + struct request_list *rp, *rp_next = 0; +#endif /***/ + struct timeval now; + + gettimeofday(&now, (struct timezone *)0); + /* + * For each request outstanding, check to see if it has expired. + */ + for(slp = Sessions; slp; slp = slp->next){ + sp = slp->session; + isp = slp->internal; +#if 1 /***/ /* simplification */ + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (timercmp(&rp->expire, &now, <)){ + /* this timer has expired */ + if (rp->retries >= sp->retries){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_TIMEOUT); +#endif + /* No more chances, delete this entry */ + sp->callback(TIMED_OUT, sp, rp->pdu->reqid, rp->pdu, sp->callback_magic); + free_one_request(isp, rp); + continue; +#endif /***/ + } else { + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct timeval tv; + + /* retransmit this pdu */ + rp->retries++; + rp->timeout <<= 1; + if (snmp_build(sp, rp->pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, rp->pdu->address, 1); + } +#endif /***/ + gettimeofday(&tv, (struct timezone *) 0); + if (sendto(isp->sd, (char *) packet, length, 0, (struct sockaddr *) &rp->pdu->address, sizeof(rp->pdu->address)) < 0) { + perror("sendto"); + } + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + } +#if 1 /***/ /* simplification */ + } +ata = data; + int origlength = length; + int ret = 0; + u_char *save_data; + + /* authenticates message and returns length if valid */ + data = snmp_auth_parse(data, &length, community, &community_length, &version); + if (data == NULL) + return -1; + + if( version != SNMP_VERSION_1 && version != SNMP_VERSION_2C && version != SNMP_VERSION_2 ) { + fprintf(stderr, "Wrong version: %ld\n", version); + return -1; + } + + save_data = data; + + data = asn_parse_header(data, &length, &msg_type); + if (data == NULL) + return -1; + pdu->command = msg_type; + + if( session->authenticator ) { + ret = session->authenticator( origdata, origlength, save_data - community_length, + community_length, session, pdu ); + if( ret < 0 ) return ret; + } + + if (pdu->command != TRP_REQ_MSG){ + data = asn_parse_int(data, &length, &type, (long *)&pdu->reqid, sizeof(pdu->reqid)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errstat, sizeof(pdu->errstat)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->errindex, sizeof(pdu->errindex)); + if (data == NULL) + return -1; + } else { + pdu->enterprise_length = MAX_NAME_LEN; + data = asn_parse_objid(data, &length, &type, objid, &pdu->enterprise_length); + if (data == NULL) + return -1; + pdu->enterprise = (oid *)calloc(1, pdu->enterprise_length * sizeof(oid)); + bcopy((char *)objid, (char *)pdu->enterprise, pdu->enterprise_length * sizeof(oid)); + + four = 4; + data = asn_parse_string(data, &length, &type, (u_char *)&pdu->agent_addr.sin_addr.s_addr, &four); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->trap_type, sizeof(pdu->trap_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->specific_type, sizeof(pdu->specific_type)); + if (data == NULL) + return -1; + data = asn_parse_int(data, &length, &type, (long *)&pdu->time, sizeof(pdu->time)); + if (data == NULL) + return -1; + } + data = asn_parse_header(data, &length, &type); + if (data == NULL) + return -1; + if (type != (u_char)(ASN_SEQUENCE | ASN_CONSTRUCTOR)) + return -1; + while((int)length > 0){ + if (pdu->variables == NULL){ + pdu->variables = vp = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + } else { + vp->next_variable = (struct variable_list *)calloc(1, sizeof(struct variable_list)); + vp = vp->next_variable; + } + vp->next_variable = NULL; + vp->val.string = NULL; + vp->name = NULL; + vp->name_length = MAX_NAME_LEN; + data = snmp_parse_var_op(data, objid, &vp->name_length, &vp->type, &vp->val_len, &var_val, (int *)&length); + if (data == NULL) + return -1; + op = (oid *)calloc(1, (unsigned)vp->name_length * sizeof(oid)); + bcopy((char *)objid, (char *)op, vp->name_length * sizeof(oid)); + vp->name = op; + + len = PACKET_LENGTH; + switch((short)vp->type){ + case ASN_INTEGER: + vp->val.integer = (long *)calloc(1, sizeof(long)); + vp->val_len = sizeof(long); + asn_parse_int(var_val, &len, &vp->type, (long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER: + case GAUGE: + case TIMETICKS: + case UINTEGER: + vp->val.integer = (long *)calloc(1, sizeof(unsigned long)); + vp->val_len = sizeof(unsigned long); + asn_parse_unsigned_int(var_val, &len, &vp->type, (unsigned long *)vp->val.integer, sizeof(vp->val.integer)); + break; + case COUNTER64: + vp->val.counter64 = (struct counter64 *)calloc(1, sizeof(struct counter64) ); + vp->val_len = sizeof(struct counter64); + asn_parse_unsigned_int64(var_val, &len, &vp->type, + (struct counter64 *)vp->val.counter64, + sizeof(*vp->val.counter64)); + break; + case ASN_OCTET_STR: + case IPADDRESS: + case OPAQUE: + case NSAP: + vp->val.string = (u_char *)calloc(1, (unsigned)vp->val_len); + asn_parse_string(var_val, &len, &vp->type, vp->val.string, &vp->val_len); + break; + case ASN_OBJECT_ID: + vp->val_len = MAX_NAME_LEN; + asn_parse_objid(var_val, &len, &vp->type, objid, &vp->val_len); + vp->val_len *= sizeof(oid); + vp->val.objid = (oid *)calloc(1, (unsigned)vp->val_len); + bcopy((char *)objid, (char *)vp->val.objid, vp->val_len); + break; + case SNMP_NOSUCHOBJECT: + case SNMP_NOSUCHINSTANCE: + case SNMP_ENDOFMIBVIEW: + case ASN_NULL: + break; + default: + fprintf(stderr, "bad type returned (%x)\n", vp->type); + break; + } + } + return ret; +} + +/* + * Sends the input pdu on the session after calling snmp_build to create + * a serialized packet. If necessary, set some of the pdu data from the + * session defaults. Add a request corresponding to this pdu to the list + * of outstanding requests on this session, then send the pdu. + * Returns the request id of the generated packet if applicable, otherwise 1. + * On any error, 0 is returned. + * The pdu is freed by snmp_send() unless a failure occured. + */ +int +snmp_send(session, pdu) + struct snmp_session *session; + struct snmp_pdu *pdu; +{ + struct session_list *slp; + struct snmp_internal_session *isp = NULL; + u_char packet[PACKET_LENGTH]; + int length = PACKET_LENGTH; + struct request_list *rp; + struct timeval tv; + + for(slp = Sessions; slp; slp = slp->next){ + if (slp->session == session){ + isp = slp->internal; + break; + } + } + + if (! pdu) { + snmp_errno = SNMPERR_GENERR; + return 0; + } + + if (isp == NULL){ + snmp_errno = SNMPERR_BAD_SESSION; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GET_RSP_MSG || pdu->command == SET_REQ_MSG + || pdu->command == GETBULK_REQ_MSG ){ + if (pdu->reqid == SNMP_DEFAULT_REQID) + pdu->reqid = ++Reqid; + if (pdu->errstat == SNMP_DEFAULT_ERRSTAT) + pdu->errstat = 0; + if (pdu->errindex == SNMP_DEFAULT_ERRINDEX) + pdu->errindex = 0; + } else { + /* fill in trap defaults */ + pdu->reqid = 1; /* give a bogus non-error reqid for traps */ + if (pdu->enterprise_length == SNMP_DEFAULT_ENTERPRISE_LENGTH){ + pdu->enterprise = (oid *)calloc(1, sizeof(DEFAULT_ENTERPRISE)); + bcopy((char *)DEFAULT_ENTERPRISE, (char *)pdu->enterprise, sizeof(DEFAULT_ENTERPRISE)); + pdu->enterprise_length = sizeof(DEFAULT_ENTERPRISE)/sizeof(oid); + } + if (pdu->time == SNMP_DEFAULT_TIME) + pdu->time = DEFAULT_TIME; + } + if (pdu->address.sin_addr.s_addr == SNMP_DEFAULT_ADDRESS){ + if (isp->addr.sin_addr.s_addr != SNMP_DEFAULT_ADDRESS){ + bcopy((char *)&isp->addr, (char *)&pdu->address, sizeof(pdu->address)); + } else { + fprintf(stderr, "No remote IP address specified\n"); + snmp_errno = SNMPERR_BAD_ADDRESS; + return 0; + } + } + + + if (snmp_build(session, pdu, packet, &length, 0) < 0){ + fprintf(stderr, "Error building packet\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, pdu->address, 1); + } +#endif /***/ + + gettimeofday(&tv, (struct timezone *)0); + if (sendto(isp->sd, (char *)packet, length, 0, (struct sockaddr *)&pdu->address, sizeof(pdu->address)) < 0){ + perror("sendto"); + snmp_errno = SNMPERR_GENERR; + return 0; + } + if (pdu->command == GET_REQ_MSG || pdu->command == GETNEXT_REQ_MSG + || pdu->command == SET_REQ_MSG || pdu->command == GETBULK_REQ_MSG ){ + /* set up to expect a response */ + rp = (struct request_list *)calloc(1, sizeof(struct request_list)); +#if 1 /***/ + if(! rp){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return 0; + } +#endif /***/ + rp->next_request = isp->requests; + isp->requests = rp; + rp->pdu = pdu; + rp->request_id = pdu->reqid; + + rp->retries = 1; + rp->timeout = session->timeout; + rp->time = tv; + tv.tv_usec += rp->timeout; + tv.tv_sec += tv.tv_usec / 1000000L; + tv.tv_usec %= 1000000L; + rp->expire = tv; +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_SEND); +#endif + } + return pdu->reqid; +} + +/* + * Frees the pdu and any malloc'd data associated with it. + */ +void +snmp_free_pdu(struct snmp_pdu * pdu) +{ + struct variable_list *vp, *ovp; + + if (! pdu) + return; + + vp = pdu->variables; + while(vp){ + if (vp->name) { + free((char *)vp->name); + } + if (vp->val.string) { + free((char *)vp->val.string); + } + ovp = vp; + vp = vp->next_variable; + free((char *)ovp); + } + if (pdu->enterprise) { + free((char *)pdu->enterprise); + } + free((char *)pdu); +} + + +/* + * Checks to see if any of the fd's set in the fdset belong to + * snmp. Each socket with it's fd set has a packet read from it + * and snmp_parse is called on the packet received. The resulting pdu + * is passed to the callback routine for that session. If the callback + * routine returns successfully, the pdu and it's request are deleted. + */ +void +snmp_read(fdset) + fd_set *fdset; +{ + struct session_list *slp; + struct snmp_session *sp; + struct snmp_internal_session *isp; + u_char packet[PACKET_LENGTH]; + struct sockaddr_in from; + ssize_t length, fromlength; + struct snmp_pdu *pdu; + struct request_list *rp /**, *orp **/ ; + + for(slp = Sessions; slp; slp = slp->next){ + if (FD_ISSET(slp->internal->sd, fdset)){ + sp = slp->session; + isp = slp->internal; + fromlength = sizeof(from); + length = recvfrom(isp->sd, (char *)packet, PACKET_LENGTH, 0, (struct sockaddr *)&from, &fromlength); + if (length == -1) { + perror("recvfrom"); + return; + } +#if 1 /***/ + if (snmp_dump_packet){ + snmp_print_packet(packet, length, from, 0); + } + pdu = (struct snmp_pdu *)calloc(1, sizeof(struct snmp_pdu)); + + if(! pdu){ + fprintf(stderr, "Out of memory!\n"); + snmp_errno = SNMPERR_GENERR; + return; + } +#endif /***/ + + pdu->address = from; + pdu->reqid = 0; + pdu->variables = NULL; + pdu->enterprise = NULL; + pdu->enterprise_length = 0; + if (snmp_parse(sp, pdu, packet, length) < 0){ + fprintf(stderr, "Mangled packet\n"); + snmp_free_pdu(pdu); + return; + } + + if (pdu->command == GET_RSP_MSG || pdu->command == REPORT_MSG){ +#if 1 /***/ /* bug fix: illegal re-use of rp killed some requests */ + struct request_list *rp_next= 0; + for(rp = isp->requests; rp; rp = rp_next){ + rp_next = rp->next_request; + if (rp->request_id == pdu->reqid){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, rp, TRACE_RECV); +#endif + if (sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic) == 1){ + /* successful, so delete request */ + free_one_request(isp, rp); + break; /* no more request with the same reqid */ + } + } + } +#endif /***/ + } else if (pdu->command == GET_REQ_MSG + || pdu->command == GETNEXT_REQ_MSG + || pdu->command == GETBULK_REQ_MSG + || pdu->command == TRP_REQ_MSG || pdu->command == SET_REQ_MSG){ +#if DEBUG_SNMPTRACE + snmp_print_trace(slp, NULL, TRACE_RECV); +#endif + sp->callback(RECEIVED_MESSAGE, sp, pdu->reqid, pdu, sp->callback_magic); + } + snmp_free_pdu(pdu); + } + } +} + +/* + * Returns info about what snmp requires from a select statement. + * numfds is the number of fds in the list that are significant. + * All file descriptors opened for SNMP are OR'd into the fdset. + * If activity occurs on any of these file descriptors, snmp_read + * should be called with that file descriptor set + * + * The timeout is the latest time that SNMP can wait for a timeout. The + * select should be done with the minimum time between timeout and any other + * timeouts necessary. This should be checked upon each invocation of select. + * If a timeout is received, snmp_timeout should be called to check if the + * timeout was for SNMP. (snmp_timeout is idempotent) + * + * Block is 1 if the select is requested to block indefinitely, rather + * than time out. If block is input as 1, the timeout value will be + * treated as undefined, but it must be available for setting in + * snmp_select_info. On return, if block is true, the value of + * timeout will be undefined. + * + * snmp_select_info returns the number of open sockets. (i.e. The + * number of sessions open) + */ +int +snmp_select_info(numfds, fdset, timeout, block) + int *numfds; + fd_set *fdset; + struct timeval *timeout; + int *block; /* should the select block until input arrives (i.e. no input) */ +{ + struct session_list *slp; + struct snmp_internal_session *isp; + struct request_list *rp; + struct timeval now, earliest; + int active = 0, requests = 0; + + timerclear(&earliest); + /* + * For each request outstanding, add it's socket to the fdset, + * and if it is the earliest timeout to expire, mark it as lowest. + */ + for(slp = Sessions; slp; slp = slp->next){ + active++; + isp = slp->internal; + if ((isp->sd + 1) > *numfds) + *numfds = (isp->sd + 1); + FD_SET(isp->sd, fdset); + if (isp->requests){ + /* found another session with outstanding requests */ + requests++; + for(rp = isp->requests; rp; rp = rp->next_request){ + if (!timerisset(&earliest) || timercmp(&rp->expire, &earliest, <)) + earliest = rp->expire; + } + } + } + if (requests == 0) /* if none are active, skip arithmetic */ + return active; + + /* + * Now find out how much time until the earliest timeout. This + * transforms earliest from an absolute time into a delta time, the + * time left until the select should timeout. + */ + gettimeofday(&now, (struct timezone *)0); + earliest.tv_sec--; /* adjust time to make arithmetic easier */ + earliest.tv_usec += 1000000L; + earliest.tv_sec -= now.tv_sec; + earliest.tv_usec -= now.tv_usec; + while (earliest.tv_usec >= 1000000L){ + earliest.tv_usec -= 1BÐ+= m +È /* >X*/ B4¨NMPTíˆ */cfor testing purposes */e key! replace... + */ + * ÿ¯ùsnmplib/snmp_api.cc.hÿ°…<Ðlib/snmp_api.c~~ñÿ±<ðÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±«=ÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²=0ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²Š=Pÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ³ +=pÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³‚ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×Áÿ³ùÿ´=ø%D(ÿ´_=à\BØÿ´©=˜4BØÿ´ø=ÈHBØÿµB>ÿµ]ÿµmÿµzÿµ >(ÿµ·ÿµÉÿµÖÿµï>@ÿ¶ÿ¶ ÿ¶4ÿ¶Pÿ¶rÿ¶~ÿ¶ˆ0ÿ¶Ÿ4¨ÿ¶·ÿ¶Ù‰èÿ·ÿ·#ÿ·/ÿ·>>Xÿ·V3/usr/people/wessels/.indent.proÿ¯èÿ¯ùÿ° ÿ°ÿ°.ÿ°?ÿ°Mÿ°[ÿ°pÿ°…ÿ°•ÿ°£ÿ°²ÿ°Åÿ°Ûÿ°ñÿ± +ÿ±ÿ±2ÿ±Fÿ±Yÿ±iÿ±{ÿ±Šÿ±™ÿ±«ÿ±ºÿ±Çÿ±Óÿ±éÿ±÷ÿ²ÿ²ÿ²ÿ²2ÿ²<ÿ²Kÿ²Wÿ²fÿ²tÿ²ÿ²Šÿ²™ÿ²¨ÿ²¶ÿ²Äÿ²Ôÿ²ãÿ²öÿ³ +ÿ³ ÿ³3ÿ³Bÿ³Sÿ³]ÿ³iÿ³sÿ³‚ÿ³‘ÿ³ ÿ³­ÿ³ºÿ³Êÿ³×ÿ³çÿ³ùÿ´ÿ´ÿ´ÿ´)ÿ´3ÿ´Cÿ´Oÿ´_ÿ´kÿ´tÿ´ÿ´ÿ´Ÿÿ´©ÿ´·ÿ´Åÿ´Òÿ´Ýÿ´íÿ´øÿµÿµÿµÿµ)ÿµ7ÿµBÿµMÿµ]ÿµmÿµzÿµ‰ÿµ ÿµ«ÿµ·ÿµÉÿµÖÿµâÿµïÿ¶ÿ¶ÿ¶ ÿ¶4ÿ¶?ÿ¶Pÿ¶bÿ¶rÿ¶~ÿ¶ˆÿ¶”ÿ¶Ÿÿ¶«ÿ¶·ÿ¶Éÿ¶Ùÿ¶íÿ·ÿ·ÿ·#ÿ·/ÿ·>ÿ·Lÿ·Vÿ·fÿ·q°>X 4¨ $  @,2ˆ…>X‚àC Ž0   ¸ude/snmp_groupvars.h~ àude/snmp_groupvars.h ŽX Ž€ ލ ŽÐ „©/*********************************************************** + Copyright 1989 by Carnegie Mellon University + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of CMU not be +used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. + CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR @@ -1149,5 +21573,3 @@ snmp_timeout() #endif /***/ } } - - diff --git a/src/acl.cc b/src/acl.cc index dbd6d43e77..73566b0dfb 100644 --- a/src/acl.cc +++ b/src/acl.cc @@ -1,6 +1,6 @@ /* - * $Id: acl.cc,v 1.119 1997/11/17 22:11:24 wessels Exp $ + * $Id: acl.cc,v 1.120 1997/11/21 01:59:14 wessels Exp $ * * DEBUG: section 28 Access Control * AUTHOR: Duane Wessels @@ -1073,7 +1073,7 @@ aclMatchProxyAuth(struct _acl_proxy_auth *p, aclCheck_t * checklist) if ((passwd = strchr(sent_user, ':')) != NULL) *passwd++ = '\0'; if (passwd == NULL) { - debug(28, 3) ("aclMatchProxyAuth: No passwd in auth blob\n"); + debug(28, 3) ("aclMatchProxyAuth: No passwd in auth blob\n"); return 0; } debug(28, 5) ("aclMatchProxyAuth: checking user %s\n", sent_user); diff --git a/src/client.cc b/src/client.cc index 7272bd5ed9..abc4b88f8e 100644 --- a/src/client.cc +++ b/src/client.cc @@ -1,6 +1,7 @@ + /* - * $Id: client.cc,v 1.41 1997/11/21 00:29:34 wessels Exp $ + * $Id: client.cc,v 1.42 1997/11/21 01:59:15 wessels Exp $ * * DEBUG: section 0 WWW Client * AUTHOR: Harvest Derived diff --git a/src/enums.h b/src/enums.h index 4b53f3d3be..38b6da419e 100644 --- a/src/enums.h +++ b/src/enums.h @@ -195,7 +195,7 @@ typedef enum { ICP_UNUSED19, ICP_UNUSED20, ICP_MISS_NOFETCH, - ICP_DENIED, + ICP_DENIED, ICP_HIT_OBJ, ICP_END } icp_opcode; diff --git a/src/main.cc b/src/main.cc index 8f535a33a7..d7ffd815a2 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,6 +1,6 @@ /* - * $Id: main.cc,v 1.193 1997/11/21 00:29:36 wessels Exp $ + * $Id: main.cc,v 1.194 1997/11/21 01:59:16 wessels Exp $ * * DEBUG: section 1 Startup and Main Loop * AUTHOR: Harvest Derived @@ -404,7 +404,7 @@ serverConnectionsOpen(void) } } #ifdef SQUID_SNMP - initSquidSnmp(); + initSquidSnmp(); #endif clientdbInit(); @@ -572,7 +572,7 @@ mainInitialize(void) configured_once = 1; #ifdef SQUID_SNMP - init_snmp(); + init_snmp(); #endif } diff --git a/src/protos.h b/src/protos.h index 88f65e12f2..3ee2d679c7 100644 --- a/src/protos.h +++ b/src/protos.h @@ -239,8 +239,8 @@ extern PF icpHandleUdp; extern PF httpAccept; extern DEFER httpAcceptDefer; #ifdef SQUID_SNMP -/*extern PF snmpHandleUdp;*/ -/*extern void initSquidSnmp();*/ +/*extern PF snmpHandleUdp; */ +/*extern void initSquidSnmp(); */ #endif /* SQUID_SNMP */ extern void icpSendERROR(int fd,