net-snmp 5.7
snmp.c
00001 /*
00002  * Simple Network Management Protocol (RFC 1067).
00003  *
00004  */
00005 /**********************************************************************
00006         Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
00007 
00008                       All Rights Reserved
00009 
00010 Permission to use, copy, modify, and distribute this software and its 
00011 documentation for any purpose and without fee is hereby granted, 
00012 provided that the above copyright notice appear in all copies and that
00013 both that copyright notice and this permission notice appear in 
00014 supporting documentation, and that the name of CMU not be
00015 used in advertising or publicity pertaining to distribution of the
00016 software without specific, written prior permission.  
00017 
00018 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
00019 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
00020 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
00021 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00022 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
00023 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
00024 SOFTWARE.
00025 ******************************************************************/
00026 
00027 #include <net-snmp/net-snmp-config.h>
00028 #include <ctype.h>
00029 
00030 #ifdef KINETICS
00031 #include "gw.h"
00032 #include "ab.h"
00033 #include "inet.h"
00034 #include "fp4/cmdmacro.h"
00035 #include "fp4/pbuf.h"
00036 #include "glob.h"
00037 #endif
00038 
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 
00042 #include <sys/types.h>
00043 #ifdef HAVE_STRING_H
00044 #include <string.h>
00045 #else
00046 #include <strings.h>
00047 #endif
00048 #if HAVE_NETINET_IN_H
00049 #include <netinet/in.h>
00050 #endif
00051 #ifdef HAVE_SYS_SELECT_H
00052 #include <sys/select.h>
00053 #endif
00054 #ifndef NULL
00055 #define NULL 0
00056 #endif
00057 
00058 #if HAVE_DMALLOC_H
00059 #include <dmalloc.h>
00060 #endif
00061 
00062 #ifdef vms
00063 #include <in.h>
00064 #endif
00065 
00066 #include <net-snmp/types.h>
00067 #include <net-snmp/output_api.h>
00068 
00069 #include <net-snmp/library/asn1.h>
00070 #include <net-snmp/library/snmp.h>      /* for "internal" definitions */
00071 #include <net-snmp/library/snmp_api.h>
00072 #include <net-snmp/library/mib.h>
00073 
00089 void
00090 xdump(const void * data, size_t length, const char *prefix)
00091 {
00092     const u_char * const cp = (const u_char*)data;
00093     int                  col, count;
00094     char                *buffer;
00095 
00096     buffer = (char *) malloc(strlen(prefix) + 80);
00097     if (!buffer) {
00098         snmp_log(LOG_NOTICE,
00099                  "xdump: malloc failed. packet-dump skipped\n");
00100         return;
00101     }
00102 
00103     count = 0;
00104     while (count < (int) length) {
00105         strcpy(buffer, prefix);
00106         sprintf(buffer + strlen(buffer), "%.4d: ", count);
00107 
00108         for (col = 0; ((count + col) < (int) length) && col < 16; col++) {
00109             sprintf(buffer + strlen(buffer), "%02X ", cp[count + col]);
00110             if (col % 4 == 3)
00111                 strcat(buffer, " ");
00112         }
00113         for (; col < 16; col++) {       /* pad end of buffer with zeros */
00114             strcat(buffer, "   ");
00115             if (col % 4 == 3)
00116                 strcat(buffer, " ");
00117         }
00118         strcat(buffer, "  ");
00119         for (col = 0; ((count + col) < (int) length) && col < 16; col++) {
00120             buffer[col + 60] =
00121                 isprint(cp[count + col]) ? cp[count + col] : '.';
00122         }
00123         buffer[col + 60] = '\n';
00124         buffer[col + 60 + 1] = 0;
00125         snmp_log(LOG_DEBUG, "%s", buffer);
00126         count += col;
00127     }
00128     snmp_log(LOG_DEBUG, "\n");
00129     free(buffer);
00130 
00131 }                               /* end xdump() */
00132 
00133 /*
00134  * u_char * snmp_parse_var_op(
00135  * u_char *data              IN - pointer to the start of object
00136  * oid *var_name             OUT - object id of variable 
00137  * int *var_name_len         IN/OUT - length of variable name 
00138  * u_char *var_val_type      OUT - type of variable (int or octet string) (one byte) 
00139  * int *var_val_len          OUT - length of variable 
00140  * u_char **var_val          OUT - pointer to ASN1 encoded value of variable 
00141  * int *listlength          IN/OUT - number of valid bytes left in var_op_list 
00142  */
00143 
00144 u_char         *
00145 snmp_parse_var_op(u_char * data,
00146                   oid * var_name,
00147                   size_t * var_name_len,
00148                   u_char * var_val_type,
00149                   size_t * var_val_len,
00150                   u_char ** var_val, size_t * listlength)
00151 {
00152     u_char          var_op_type;
00153     size_t          var_op_len = *listlength;
00154     u_char         *var_op_start = data;
00155 
00156     data = asn_parse_sequence(data, &var_op_len, &var_op_type,
00157                               (ASN_SEQUENCE | ASN_CONSTRUCTOR), "var_op");
00158     if (data == NULL) {
00159         /*
00160          * msg detail is set 
00161          */
00162         return NULL;
00163     }
00164     DEBUGDUMPHEADER("recv", "Name");
00165     data =
00166         asn_parse_objid(data, &var_op_len, &var_op_type, var_name,
00167                         var_name_len);
00168     DEBUGINDENTLESS();
00169     if (data == NULL) {
00170         ERROR_MSG("No OID for variable");
00171         return NULL;
00172     }
00173     if (var_op_type !=
00174         (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE | ASN_OBJECT_ID))
00175         return NULL;
00176     *var_val = data;            /* save pointer to this object */
00177     /*
00178      * find out what type of object this is 
00179      */
00180     data = asn_parse_header(data, &var_op_len, var_val_type);
00181     if (data == NULL) {
00182         ERROR_MSG("No header for value");
00183         return NULL;
00184     }
00185     /*
00186      * XXX no check for type! 
00187      */
00188     *var_val_len = var_op_len;
00189     data += var_op_len;
00190     *listlength -= (int) (data - var_op_start);
00191     return data;
00192 }
00193 
00194 /*
00195  * u_char * snmp_build_var_op(
00196  * u_char *data      IN - pointer to the beginning of the output buffer
00197  * oid *var_name        IN - object id of variable 
00198  * int *var_name_len    IN - length of object id 
00199  * u_char var_val_type  IN - type of variable 
00200  * int    var_val_len   IN - length of variable 
00201  * u_char *var_val      IN - value of variable 
00202  * int *listlength      IN/OUT - number of valid bytes left in
00203  * output buffer 
00204  */
00205 
00206 u_char         *
00207 snmp_build_var_op(u_char * data,
00208                   oid * var_name,
00209                   size_t * var_name_len,
00210                   u_char var_val_type,
00211                   size_t var_val_len,
00212                   u_char * var_val, size_t * listlength)
00213 {
00214     size_t          dummyLen, headerLen;
00215     u_char         *dataPtr;
00216 
00217     dummyLen = *listlength;
00218     dataPtr = data;
00219 #if 0
00220     data = asn_build_sequence(data, &dummyLen,
00221                               (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
00222                               0);
00223     if (data == NULL) {
00224         return NULL;
00225     }
00226 #endif
00227     if (dummyLen < 4)
00228         return NULL;
00229     data += 4;
00230     dummyLen -= 4;
00231 
00232     headerLen = data - dataPtr;
00233     *listlength -= headerLen;
00234     DEBUGDUMPHEADER("send", "Name");
00235     data = asn_build_objid(data, listlength,
00236                            (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
00237                                      ASN_OBJECT_ID), var_name,
00238                            *var_name_len);
00239     DEBUGINDENTLESS();
00240     if (data == NULL) {
00241         ERROR_MSG("Can't build OID for variable");
00242         return NULL;
00243     }
00244     DEBUGDUMPHEADER("send", "Value");
00245     switch (var_val_type) {
00246     case ASN_INTEGER:
00247         data = asn_build_int(data, listlength, var_val_type,
00248                              (long *) var_val, var_val_len);
00249         break;
00250     case ASN_GAUGE:
00251     case ASN_COUNTER:
00252     case ASN_TIMETICKS:
00253     case ASN_UINTEGER:
00254         data = asn_build_unsigned_int(data, listlength, var_val_type,
00255                                       (u_long *) var_val, var_val_len);
00256         break;
00257 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
00258     case ASN_OPAQUE_COUNTER64:
00259     case ASN_OPAQUE_U64:
00260 #endif
00261     case ASN_COUNTER64:
00262         data = asn_build_unsigned_int64(data, listlength, var_val_type,
00263                                         (struct counter64 *) var_val,
00264                                         var_val_len);
00265         break;
00266     case ASN_OCTET_STR:
00267     case ASN_IPADDRESS:
00268     case ASN_OPAQUE:
00269     case ASN_NSAP:
00270         data = asn_build_string(data, listlength, var_val_type,
00271                                 var_val, var_val_len);
00272         break;
00273     case ASN_OBJECT_ID:
00274         data = asn_build_objid(data, listlength, var_val_type,
00275                                (oid *) var_val, var_val_len / sizeof(oid));
00276         break;
00277     case ASN_NULL:
00278         data = asn_build_null(data, listlength, var_val_type);
00279         break;
00280     case ASN_BIT_STR:
00281         data = asn_build_bitstring(data, listlength, var_val_type,
00282                                    var_val, var_val_len);
00283         break;
00284     case SNMP_NOSUCHOBJECT:
00285     case SNMP_NOSUCHINSTANCE:
00286     case SNMP_ENDOFMIBVIEW:
00287         data = asn_build_null(data, listlength, var_val_type);
00288         break;
00289 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
00290     case ASN_OPAQUE_FLOAT:
00291         data = asn_build_float(data, listlength, var_val_type,
00292                                (float *) var_val, var_val_len);
00293         break;
00294     case ASN_OPAQUE_DOUBLE:
00295         data = asn_build_double(data, listlength, var_val_type,
00296                                 (double *) var_val, var_val_len);
00297         break;
00298     case ASN_OPAQUE_I64:
00299         data = asn_build_signed_int64(data, listlength, var_val_type,
00300                                       (struct counter64 *) var_val,
00301                                       var_val_len);
00302         break;
00303 #endif                          /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
00304     default:
00305         {
00306         char error_buf[64];
00307         snprintf(error_buf, sizeof(error_buf),
00308                 "wrong type in snmp_build_var_op: %d", var_val_type);
00309         ERROR_MSG(error_buf);
00310         data = NULL;
00311         }
00312     }
00313     DEBUGINDENTLESS();
00314     if (data == NULL) {
00315         return NULL;
00316     }
00317     dummyLen = (data - dataPtr) - headerLen;
00318 
00319     asn_build_sequence(dataPtr, &dummyLen,
00320                        (u_char) (ASN_SEQUENCE | ASN_CONSTRUCTOR),
00321                        dummyLen);
00322     return data;
00323 }
00324 
00325 #ifdef NETSNMP_USE_REVERSE_ASNENCODING
00326 int
00327 snmp_realloc_rbuild_var_op(u_char ** pkt, size_t * pkt_len,
00328                            size_t * offset, int allow_realloc,
00329                            const oid * var_name, size_t * var_name_len,
00330                            u_char var_val_type,
00331                            u_char * var_val, size_t var_val_len)
00332 {
00333     size_t          start_offset = *offset;
00334     int             rc = 0;
00335 
00336     /*
00337      * Encode the value.  
00338      */
00339     DEBUGDUMPHEADER("send", "Value");
00340 
00341     switch (var_val_type) {
00342     case ASN_INTEGER:
00343         rc = asn_realloc_rbuild_int(pkt, pkt_len, offset, allow_realloc,
00344                                     var_val_type, (long *) var_val,
00345                                     var_val_len);
00346         break;
00347 
00348     case ASN_GAUGE:
00349     case ASN_COUNTER:
00350     case ASN_TIMETICKS:
00351     case ASN_UINTEGER:
00352         rc = asn_realloc_rbuild_unsigned_int(pkt, pkt_len, offset,
00353                                              allow_realloc, var_val_type,
00354                                              (u_long *) var_val,
00355                                              var_val_len);
00356         break;
00357 
00358 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
00359     case ASN_OPAQUE_COUNTER64:
00360     case ASN_OPAQUE_U64:
00361 #endif
00362     case ASN_COUNTER64:
00363         rc = asn_realloc_rbuild_unsigned_int64(pkt, pkt_len, offset,
00364                                                allow_realloc, var_val_type,
00365                                                (struct counter64 *)
00366                                                var_val, var_val_len);
00367         break;
00368 
00369     case ASN_OCTET_STR:
00370     case ASN_IPADDRESS:
00371     case ASN_OPAQUE:
00372     case ASN_NSAP:
00373         rc = asn_realloc_rbuild_string(pkt, pkt_len, offset, allow_realloc,
00374                                        var_val_type, var_val, var_val_len);
00375         break;
00376 
00377     case ASN_OBJECT_ID:
00378         rc = asn_realloc_rbuild_objid(pkt, pkt_len, offset, allow_realloc,
00379                                       var_val_type, (oid *) var_val,
00380                                       var_val_len / sizeof(oid));
00381         break;
00382 
00383     case ASN_NULL:
00384         rc = asn_realloc_rbuild_null(pkt, pkt_len, offset, allow_realloc,
00385                                      var_val_type);
00386         break;
00387 
00388     case ASN_BIT_STR:
00389         rc = asn_realloc_rbuild_bitstring(pkt, pkt_len, offset,
00390                                           allow_realloc, var_val_type,
00391                                           var_val, var_val_len);
00392         break;
00393 
00394     case SNMP_NOSUCHOBJECT:
00395     case SNMP_NOSUCHINSTANCE:
00396     case SNMP_ENDOFMIBVIEW:
00397         rc = asn_realloc_rbuild_null(pkt, pkt_len, offset, allow_realloc,
00398                                      var_val_type);
00399         break;
00400 
00401 #ifdef NETSNMP_WITH_OPAQUE_SPECIAL_TYPES
00402     case ASN_OPAQUE_FLOAT:
00403         rc = asn_realloc_rbuild_float(pkt, pkt_len, offset, allow_realloc,
00404                                       var_val_type, (float *) var_val,
00405                                       var_val_len);
00406         break;
00407 
00408     case ASN_OPAQUE_DOUBLE:
00409         rc = asn_realloc_rbuild_double(pkt, pkt_len, offset, allow_realloc,
00410                                        var_val_type, (double *) var_val,
00411                                        var_val_len);
00412         break;
00413 
00414     case ASN_OPAQUE_I64:
00415         rc = asn_realloc_rbuild_signed_int64(pkt, pkt_len, offset,
00416                                              allow_realloc, var_val_type,
00417                                              (struct counter64 *) var_val,
00418                                              var_val_len);
00419         break;
00420 #endif                          /* NETSNMP_WITH_OPAQUE_SPECIAL_TYPES */
00421     default:
00422         {
00423         char error_buf[64];
00424         snprintf(error_buf, sizeof(error_buf),
00425                 "wrong type in snmp_realloc_rbuild_var_op: %d", var_val_type);
00426         ERROR_MSG(error_buf);
00427         rc = 0;
00428         }
00429     }
00430     DEBUGINDENTLESS();
00431 
00432     if (rc == 0) {
00433         return 0;
00434     }
00435 
00436     /*
00437      * Build the OID.  
00438      */
00439 
00440     DEBUGDUMPHEADER("send", "Name");
00441     rc = asn_realloc_rbuild_objid(pkt, pkt_len, offset, allow_realloc,
00442                                   (u_char) (ASN_UNIVERSAL | ASN_PRIMITIVE |
00443                                             ASN_OBJECT_ID), var_name,
00444                                   *var_name_len);
00445     DEBUGINDENTLESS();
00446     if (rc == 0) {
00447         ERROR_MSG("Can't build OID for variable");
00448         return 0;
00449     }
00450 
00451     /*
00452      * Build the sequence header.  
00453      */
00454 
00455     rc = asn_realloc_rbuild_sequence(pkt, pkt_len, offset, allow_realloc,
00456                                      (u_char) (ASN_SEQUENCE |
00457                                                ASN_CONSTRUCTOR),
00458                                      *offset - start_offset);
00459     return rc;
00460 }
00461 
00462 #endif                          /* NETSNMP_USE_REVERSE_ASNENCODING */