diff packages/net/snmp/lib/current/src/tools.c @ 103:95f3e12a6327 ecos-sw-2000-06-23

Merge from eCos master repository on 2000-06-23-16:41:10-BST
author jlarmour
date Fri, 23 Jun 2000 17:06:31 +0000
parents
children e0c0827131d1
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/packages/net/snmp/lib/current/src/tools.c
@@ -0,0 +1,635 @@
+//==========================================================================
+//
+//      ./lib/current/src/tools.c
+//
+//
+//==========================================================================
+//####COPYRIGHTBEGIN####
+//                                                                          
+// -------------------------------------------                              
+// The contents of this file are subject to the Red Hat eCos Public License 
+// Version 1.1 (the "License"); you may not use this file except in         
+// compliance with the License.  You may obtain a copy of the License at    
+// http://www.redhat.com/                                                   
+//                                                                          
+// Software distributed under the License is distributed on an "AS IS"      
+// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the 
+// License for the specific language governing rights and limitations under 
+// the License.                                                             
+//                                                                          
+// The Original Code is eCos - Embedded Configurable Operating System,      
+// released September 30, 1998.                                             
+//                                                                          
+// The Initial Developer of the Original Code is Red Hat.                   
+// Portions created by Red Hat are                                          
+// Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             
+// All Rights Reserved.                                                     
+// -------------------------------------------                              
+//                                                                          
+//####COPYRIGHTEND####
+//####UCDSNMPCOPYRIGHTBEGIN####
+//
+// -------------------------------------------
+//
+// Portions of this software may have been derived from the UCD-SNMP
+// project,  <http://ucd-snmp.ucdavis.edu/>  from the University of
+// California at Davis, which was originally based on the Carnegie Mellon
+// University SNMP implementation.  Portions of this software are therefore
+// covered by the appropriate copyright disclaimers included herein.
+//
+// The release used was version 4.1.2 of May 2000.  "ucd-snmp-4.1.2"
+// -------------------------------------------
+//
+//####UCDSNMPCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s):    hmt
+// Contributors: hmt
+// Date:         2000-05-30
+// Purpose:      Port of UCD-SNMP distribution to eCos.
+// Description:  
+//              
+//
+//####DESCRIPTIONEND####
+//
+//==========================================================================
+/********************************************************************
+       Copyright 1989, 1991, 1992 by Carnegie Mellon University
+
+			  Derivative Work -
+Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
+
+			 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 appears in all copies and
+that both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of CMU and The Regents of
+the University of California not be used in advertising or publicity
+pertaining to distribution of the software without specific written
+permission.
+
+CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
+WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL CMU OR
+THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
+INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+FROM THE 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.
+*********************************************************************/
+/*
+ * tools.c
+ */
+
+#include <config.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <sys/types.h>
+#if TIME_WITH_SYS_TIME
+# ifdef WIN32
+#  include <sys/timeb.h>
+# else
+#  include <sys/time.h>
+# endif
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+#  include <sys/time.h> 
+# else
+#  include <time.h>
+# endif
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_WINSOCK_H
+#include <winsock.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#if HAVE_DMALLOC_H
+#include <dmalloc.h>
+#endif
+
+#include "asn1.h" 
+#include "system.h"
+#include "snmp_api.h"
+#include "snmp_debug.h"
+#include "snmp_debug.h"
+#include "tools.h"
+#include "mib.h"
+#include "scapi.h" 
+
+
+/*******************************************************************-o-******
+ * free_zero
+ *
+ * Parameters:
+ *	*buf	Pointer at bytes to free.
+ *	size	Number of bytes in buf.
+ */
+void
+free_zero(void *buf, size_t size)
+{
+	if (buf) {
+		memset(buf, 0, size);
+		free(buf);
+	}
+
+}  /* end free_zero() */
+
+
+
+
+/*******************************************************************-o-******
+ * malloc_random
+ *
+ * Parameters:
+ *	size	Number of bytes to malloc() and fill with random bytes.
+ *      
+ * Returns pointer to allocaed & set buffer on success, size contains
+ * number of random bytes filled.
+ *
+ * buf is NULL and *size set to KMT error value upon failure.
+ *
+ */
+u_char *
+malloc_random(size_t *size)
+{
+	int	 rval	= SNMPERR_SUCCESS;
+	u_char	*buf	= (u_char *)calloc (1, *size);
+
+	if (buf) {
+		rval = sc_random(buf, size);
+
+		if (rval < 0) {
+			free_zero(buf, *size);
+			buf = NULL;
+		} else {
+			*size = rval;
+		}
+	}
+
+	return buf;
+
+}  /* end malloc_random() */
+
+
+
+
+/*******************************************************************-o-******
+ * memdup
+ *
+ * Parameters:
+ *	to       Pointer to allocate and copy memory to.
+ *      from     Pointer to copy memory from.
+ *      size     Size of the data to be copied.
+ *      
+ * Returns
+ *	SNMPERR_SUCCESS	On success.
+ *      SNMPERR_GENERR	On failure.
+ */
+int
+memdup(u_char **to, const u_char *from, size_t size)
+{
+  if (to == NULL)
+    return SNMPERR_GENERR;
+  if (from == NULL) {
+    *to = NULL;
+    return SNMPERR_SUCCESS;
+  }
+  if ((*to = (u_char *)malloc(size)) == NULL)
+    return SNMPERR_GENERR;
+  memcpy(*to, from, size);
+  return SNMPERR_SUCCESS;
+
+}  /* end memdup() */
+
+
+
+
+/*******************************************************************-o-******
+ * binary_to_hex
+ *
+ * Parameters:
+ *	*input		Binary data.
+ *	len		Length of binary data.
+ *	**output	NULL terminated string equivalent in hex.
+ *      
+ * Returns:
+ *	olen	Length of output string not including NULL terminator.
+ *
+ * FIX	Is there already one of these in the UCD SNMP codebase?
+ *	The old one should be used, or this one should be moved to
+ *	snmplib/snmp_api.c.
+ */
+u_int
+binary_to_hex(const u_char *input, size_t len, char **output)
+{
+	u_int	olen	= (len * 2) + 1;
+	char	*s	= (char *) calloc(1,olen),
+		*op	= s;
+	const u_char *ip	= input;
+
+
+	while (ip-input < (int)len) {
+		*op++ = VAL2HEX( (*ip >> 4) & 0xf );
+		*op++ = VAL2HEX( *ip & 0xf );
+		ip++;
+	}
+	*op = '\0';
+	
+	*output = s;
+	return olen;
+
+}  /* end binary_to_hex() */
+
+
+
+
+/*******************************************************************-o-******
+ * hex_to_binary2
+ *
+ * Parameters:
+ *	*input		Printable data in base16.
+ *	len		Length in bytes of data.
+ *	**output	Binary data equivalent to input.
+ *      
+ * Returns:
+ *	SNMPERR_GENERR	Failure.
+ *	<len>		Otherwise, Length of allocated string.
+ *
+ *
+ * Input of an odd length is right aligned.
+ *
+ * FIX	Another version of "hex-to-binary" which takes odd length input
+ *	strings.  It also allocates the memory to hold the binary data.
+ *	Should be integrated with the official hex_to_binary() function.
+ */
+int
+hex_to_binary2(const u_char *input, size_t len, char **output)
+{
+	u_int	olen	= (len/2) + (len%2);
+	char	*s	= (char *)calloc (1,olen),
+		*op	= s;
+	const u_char *ip	= input;
+
+
+	*output = NULL;
+	*op = 0;
+	if (len%2) {
+		if(!isxdigit(*ip)) goto hex_to_binary2_quit;
+		*op++ = HEX2VAL( *ip );		ip++;
+	}
+
+	while (ip-input < (int)len) {
+		if(!isxdigit(*ip)) goto hex_to_binary2_quit;
+		*op = HEX2VAL( *ip ) << 4;	ip++;
+
+		if(!isxdigit(*ip)) goto hex_to_binary2_quit;
+		*op++ += HEX2VAL( *ip );	ip++;
+	}
+
+	*output = s;	
+	return olen;
+
+hex_to_binary2_quit:
+	free_zero(s, olen);
+	return -1;
+
+}  /* end hex_to_binary2() */
+
+
+
+
+/*******************************************************************-o-******
+ * dump_chunk
+ *
+ * Parameters:
+ *	*title	(May be NULL.)
+ *	*buf
+ *	 size
+ */
+void
+dump_chunk(const char *debugtoken, const char *title, const u_char *buf, int size)
+{
+	u_int		printunit = 64;		/* XXX  Make global. */
+	char		chunk[SNMP_MAXBUF],
+			*s, *sp;
+
+	if ( title && (*title != '\0') ) {
+          DEBUGMSGTL((debugtoken, "%s\n", title));
+	}
+
+
+	memset(chunk, 0, SNMP_MAXBUF);
+	size = binary_to_hex(buf, size, &s);
+	sp   = s;
+
+	while (size > 0)
+	{
+		if (size > (int)printunit) {
+			strncpy(chunk, sp, printunit);	
+			chunk[printunit] = '\0';
+			DEBUGMSGTL((debugtoken, "\t%s\n", chunk));
+		} else {
+			DEBUGMSGTL((debugtoken, "\t%s\n", sp));
+		}
+
+		sp	+= printunit;
+		size	-= printunit;
+	}
+
+
+	SNMP_FREE(s);
+
+}  /* end dump_chunk() */
+
+
+
+
+/*******************************************************************-o-******
+ * dump_snmpEngineID
+ *
+ * Parameters:
+ *	*estring
+ *	*estring_len
+ *      
+ * Returns:
+ *	Allocated memory pointing to a string of buflen char representing
+ *	a printf'able form of the snmpEngineID.
+ *
+ *	-OR- NULL on error.
+ *
+ *
+ * Translates the snmpEngineID TC into a printable string.  From RFC 2271,
+ * Section 5 (pp. 36-37):
+ *
+ * First bit:	0	Bit string structured by means non-SNMPv3.
+ *  		1	Structure described by SNMPv3 SnmpEngineID TC.
+ *  
+ * Bytes 1-4:		Enterprise ID.  (High bit of first byte is ignored.)
+ *  
+ * Byte 5:	0	(RESERVED by IANA.)
+ *  		1	IPv4 address.		(   4 octets)
+ *  		2	IPv6 address.		(  16 octets)
+ *  		3	MAC address.		(   6 octets)
+ *  		4	Locally defined text.	(0-27 octets)
+ *  		5	Locally defined octets.	(0-27 octets)
+ *  		6-127	(RESERVED for enterprise.)
+ *  
+ * Bytes 6-32:		(Determined by byte 5.)
+ *  
+ *
+ * Non-printable characters are given in hex.  Text is given in quotes.
+ * IP and MAC addresses are given in standard (UN*X) conventions.  Sections
+ * are comma separated.
+ *
+ * esp, remaining_len and s trace the state of the constructed buffer.
+ * s will be defined if there is something to return, and it will point
+ * to the end of the constructed buffer.
+ *
+ *
+ * ASSUME  "Text" means printable characters.
+ *
+ * XXX	Must the snmpEngineID always have a minimum length of 12?
+ *	(Cf. part 2 of the TC definition.)
+ * XXX	Does not enforce upper-bound of 32 bytes.
+ * XXX	Need a switch to decide whether to use DNS name instead of a simple
+ *	IP address.
+ *
+ * FIX	Use something other than sprint_hexstring which doesn't add 
+ *	trailing spaces and (sometimes embedded) newlines...
+ */
+#ifdef SNMP_TESTING_CODE
+char *
+dump_snmpEngineID(const u_char *estring, size_t *estring_len)
+{
+#define eb(b)	( *(esp+b) & 0xff )
+
+	int		 rval		= SNMPERR_SUCCESS,
+                         gotviolation	= 0,
+                         slen           = 0;
+	u_int	 	 remaining_len;
+
+	char	 	 buf[SNMP_MAXBUF],
+			*s = NULL,
+			*t;
+        const u_char    *esp = estring;
+
+	struct	in_addr	 iaddr;
+
+
+
+	/*
+	 * Sanity check.
+	 */
+	if ( !estring || (*estring_len <= 0) ) {
+		QUITFUN(SNMPERR_GENERR, dump_snmpEngineID_quit);
+	}
+	remaining_len = *estring_len;
+	memset(buf, 0, SNMP_MAXBUF);
+
+
+
+	/*
+	 * Test first bit.  Return immediately with a hex string, or
+	 * begin by formatting the enterprise ID.
+	 */
+	if ( !(*esp & 0x80) ) {
+		sprint_hexstring(buf, esp, remaining_len);
+		s  = strchr(buf, '\0');
+		s -= 1;
+		goto dump_snmpEngineID_quit;
+	}
+
+	s = buf;
+	s += sprintf(s, "enterprise %d, ",	((*(esp+0)&0x7f) << 24) |
+						((*(esp+1)&0xff) << 16) |
+						((*(esp+2)&0xff) <<  8) |
+						((*(esp+3)&0xff)) );
+						/* XXX  Ick. */
+
+	if (remaining_len < 5) {	/* XXX	Violating string. */
+		goto dump_snmpEngineID_quit;
+	}
+
+	esp += 4;		/* Incremented one more in the switch below. */
+	remaining_len -= 5;
+
+
+
+	/*
+	 * Act on the fifth byte.
+	 */
+	switch ((int) *esp++) {
+	case 1:					/* IPv4 address. */
+
+		if (remaining_len < 4) goto dump_snmpEngineID_violation;
+		memcpy(&iaddr.s_addr, esp, 4);
+
+		if ( !(t = inet_ntoa(iaddr)) ) goto dump_snmpEngineID_violation;
+		s += sprintf(s, "%s", t);
+
+		esp += 4;
+		remaining_len -= 4;
+		break;
+
+	case 2:					/* IPv6 address. */
+
+		if (remaining_len < 16) goto dump_snmpEngineID_violation;
+
+		s += sprintf(	s,
+				"%02X%02X %02X%02X %02X%02X %02X%02X::"
+				"%02X%02X %02X%02X %02X%02X %02X%02X",
+					eb(0),  eb(1),  eb(2),  eb(3),
+					eb(4),  eb(5),  eb(6),  eb(7),
+					eb(8),  eb(9),  eb(10), eb(11),
+					eb(12), eb(13), eb(14), eb(15) );
+
+		esp += 16;
+		remaining_len -= 16;
+		break;
+
+	case 3:					/* MAC address. */
+
+		if (remaining_len < 6) goto dump_snmpEngineID_violation;
+
+		s += sprintf( s, "%02X:%02X:%02X:%02X:%02X:%02X",
+			eb(0), eb(1), eb(2), eb(3), eb(4), eb(5) );
+
+		esp += 6;
+		remaining_len -= 6;
+		break;
+
+	case 4:					/* Text. */
+
+                /* Doesn't exist on all (many) architectures */
+                /* s += snprintf(s, remaining_len+3, "\"%s\"", esp); */
+		s += sprintf(s, "\"%s\"", esp);
+		goto dump_snmpEngineID_quit;
+		break;	/*NOTREACHED*/
+
+	case 5:					/* Octets. */
+
+		sprint_hexstring(s, esp, remaining_len);
+		s  = strchr(buf, '\0');
+		s -= 1;
+		goto dump_snmpEngineID_quit;
+		break;	/*NOTREACHED*/
+
+
+dump_snmpEngineID_violation:
+	case 0:					/* Violation of RESERVED, 
+						 *   -OR- of expected length.
+						 */
+		gotviolation = 1;
+		s += sprintf(s, "!!! ");
+
+	default:				/* Unknown encoding. */
+
+		if ( !gotviolation ) {
+			s += sprintf(s, "??? ");
+		}
+		sprint_hexstring(s, esp, remaining_len);
+		s  = strchr(buf, '\0');
+		s -= 1;
+
+		goto dump_snmpEngineID_quit;
+
+	}  /* endswitch */
+
+
+
+	/*
+	 * Cases 1-3 (IP and MAC addresses) should not have trailing
+	 * octets, but perhaps they do.  Throw them in too.  XXX
+	 */
+	if (remaining_len > 0) {
+		s += sprintf(s, " (??? ");
+
+		sprint_hexstring(s, esp, remaining_len);
+		s  = strchr(buf, '\0');
+		s -= 1;
+
+		s += sprintf(s, ")");
+	}
+
+
+
+dump_snmpEngineID_quit:
+	if (s) {
+                slen = s-buf+1;
+		s = calloc(1,slen);
+		memcpy(s, buf, (slen)-1);
+	}
+
+	memset(buf, 0, SNMP_MAXBUF);	/* XXX -- Overkill? XXX: Yes! */
+
+	return s;
+
+#undef eb
+}  /* end dump_snmpEngineID() */
+#endif /* SNMP_TESTING_CODE */
+
+
+/*
+ * create a new time marker.
+ * NOTE: Caller must free time marker when no longer needed.
+ */
+marker_t atime_newMarker(void)
+{
+  marker_t pm = (marker_t)calloc(1,sizeof(struct timeval));
+  gettimeofday((struct timeval *)pm, 0);
+  return pm;
+}
+
+/*
+ * set a time marker.
+ */
+void atime_setMarker(marker_t pm)
+{
+  if (! pm) return;
+
+  gettimeofday((struct timeval *)pm, 0);
+}
+
+/*
+ * Test: Has (marked time plus delta) exceeded current time ?
+ * Returns 0 if test fails or cannot be tested (no marker).
+ */
+int atime_ready( marker_t pm, int deltaT)
+{
+  struct timeval txdelta, txnow;
+  if (! pm) return 0;
+
+  memcpy((void *)&txdelta, pm, sizeof(txdelta));
+  while (deltaT > 1000) {
+     txdelta.tv_sec ++;
+     deltaT -= 1000;
+  }
+  txdelta.tv_usec = (deltaT * 1000) + txdelta.tv_usec;
+
+  gettimeofday(&txnow, 0);
+  if (timercmp(&txnow, &txdelta, <))
+        return 0;
+
+  return 1;
+}