1 //==========================================================================
3 // ./lib/current/src/tools.c
6 //==========================================================================
7 //####ECOSGPLCOPYRIGHTBEGIN####
8 // -------------------------------------------
9 // This file is part of eCos, the Embedded Configurable Operating System.
10 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // eCos is free software; you can redistribute it and/or modify it under
13 // the terms of the GNU General Public License as published by the Free
14 // Software Foundation; either version 2 or (at your option) any later version.
16 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
17 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 // You should have received a copy of the GNU General Public License along
22 // with eCos; if not, write to the Free Software Foundation, Inc.,
23 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 // As a special exception, if other files instantiate templates or use macros
26 // or inline functions from this file, or you compile this file and link it
27 // with other works to produce a work based on this file, this file does not
28 // by itself cause the resulting work to be covered by the GNU General Public
29 // License. However the source code for this file must still be made available
30 // in accordance with section (3) of the GNU General Public License.
32 // This exception does not invalidate any other reasons why a work based on
33 // this file might be covered by the GNU General Public License.
35 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
36 // at http://sources.redhat.com/ecos/ecos-license/
37 // -------------------------------------------
38 //####ECOSGPLCOPYRIGHTEND####
39 //####UCDSNMPCOPYRIGHTBEGIN####
41 // -------------------------------------------
43 // Portions of this software may have been derived from the UCD-SNMP
44 // project, <http://ucd-snmp.ucdavis.edu/> from the University of
45 // California at Davis, which was originally based on the Carnegie Mellon
46 // University SNMP implementation. Portions of this software are therefore
47 // covered by the appropriate copyright disclaimers included herein.
49 // The release used was version 4.1.2 of May 2000. "ucd-snmp-4.1.2"
50 // -------------------------------------------
52 //####UCDSNMPCOPYRIGHTEND####
53 //==========================================================================
54 //#####DESCRIPTIONBEGIN####
59 // Purpose: Port of UCD-SNMP distribution to eCos.
63 //####DESCRIPTIONEND####
65 //==========================================================================
66 /********************************************************************
67 Copyright 1989, 1991, 1992 by Carnegie Mellon University
70 Copyright 1996, 1998, 1999, 2000 The Regents of the University of California
74 Permission to use, copy, modify and distribute this software and its
75 documentation for any purpose and without fee is hereby granted,
76 provided that the above copyright notice appears in all copies and
77 that both that copyright notice and this permission notice appear in
78 supporting documentation, and that the name of CMU and The Regents of
79 the University of California not be used in advertising or publicity
80 pertaining to distribution of the software without specific written
83 CMU AND THE REGENTS OF THE UNIVERSITY OF CALIFORNIA DISCLAIM ALL
84 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
85 WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU OR
86 THE REGENTS OF THE UNIVERSITY OF CALIFORNIA BE LIABLE FOR ANY SPECIAL,
87 INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
88 FROM THE LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
89 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
90 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
91 *********************************************************************/
100 #include <sys/types.h>
101 #if TIME_WITH_SYS_TIME
103 # include <sys/timeb.h>
105 # include <sys/time.h>
110 # include <sys/time.h>
115 #ifdef HAVE_SYS_SOCKET_H
116 #include <sys/socket.h>
129 #ifdef HAVE_NETINET_IN_H
130 #include <netinet/in.h>
132 #ifdef HAVE_ARPA_INET_H
133 #include <arpa/inet.h>
142 #include "snmp_api.h"
143 #include "snmp_debug.h"
144 #include "snmp_debug.h"
150 /*******************************************************************-o-******
154 * *buf Pointer at bytes to free.
155 * size Number of bytes in buf.
158 free_zero(void *buf, size_t size)
161 memset(buf, 0, size);
165 } /* end free_zero() */
170 /*******************************************************************-o-******
174 * size Number of bytes to malloc() and fill with random bytes.
176 * Returns pointer to allocaed & set buffer on success, size contains
177 * number of random bytes filled.
179 * buf is NULL and *size set to KMT error value upon failure.
183 malloc_random(size_t *size)
185 int rval = SNMPERR_SUCCESS;
186 u_char *buf = (u_char *)calloc (1, *size);
189 rval = sc_random(buf, size);
192 free_zero(buf, *size);
201 } /* end malloc_random() */
206 /*******************************************************************-o-******
210 * to Pointer to allocate and copy memory to.
211 * from Pointer to copy memory from.
212 * size Size of the data to be copied.
215 * SNMPERR_SUCCESS On success.
216 * SNMPERR_GENERR On failure.
219 memdup(u_char **to, const u_char *from, size_t size)
222 return SNMPERR_GENERR;
225 return SNMPERR_SUCCESS;
227 if ((*to = (u_char *)malloc(size)) == NULL)
228 return SNMPERR_GENERR;
229 memcpy(*to, from, size);
230 return SNMPERR_SUCCESS;
237 /*******************************************************************-o-******
241 * *input Binary data.
242 * len Length of binary data.
243 * **output NULL terminated string equivalent in hex.
246 * olen Length of output string not including NULL terminator.
248 * FIX Is there already one of these in the UCD SNMP codebase?
249 * The old one should be used, or this one should be moved to
250 * snmplib/snmp_api.c.
253 binary_to_hex(const u_char *input, size_t len, char **output)
255 u_int olen = (len * 2) + 1;
256 char *s = (char *) calloc(1,olen),
258 const u_char *ip = input;
261 while (ip-input < (int)len) {
262 *op++ = VAL2HEX( (*ip >> 4) & 0xf );
263 *op++ = VAL2HEX( *ip & 0xf );
271 } /* end binary_to_hex() */
276 /*******************************************************************-o-******
280 * *input Printable data in base16.
281 * len Length in bytes of data.
282 * **output Binary data equivalent to input.
285 * SNMPERR_GENERR Failure.
286 * <len> Otherwise, Length of allocated string.
289 * Input of an odd length is right aligned.
291 * FIX Another version of "hex-to-binary" which takes odd length input
292 * strings. It also allocates the memory to hold the binary data.
293 * Should be integrated with the official hex_to_binary() function.
296 hex_to_binary2(const u_char *input, size_t len, char **output)
298 u_int olen = (len/2) + (len%2);
299 char *s = (char *)calloc (1,olen),
301 const u_char *ip = input;
307 if(!isxdigit(*ip)) goto hex_to_binary2_quit;
308 *op++ = HEX2VAL( *ip ); ip++;
311 while (ip-input < (int)len) {
312 if(!isxdigit(*ip)) goto hex_to_binary2_quit;
313 *op = HEX2VAL( *ip ) << 4; ip++;
315 if(!isxdigit(*ip)) goto hex_to_binary2_quit;
316 *op++ += HEX2VAL( *ip ); ip++;
326 } /* end hex_to_binary2() */
331 /*******************************************************************-o-******
335 * *title (May be NULL.)
340 dump_chunk(const char *debugtoken, const char *title, const u_char *buf, int size)
342 u_int printunit = 64; /* XXX Make global. */
343 char chunk[SNMP_MAXBUF],
346 if ( title && (*title != '\0') ) {
347 DEBUGMSGTL((debugtoken, "%s\n", title));
351 memset(chunk, 0, SNMP_MAXBUF);
352 size = binary_to_hex(buf, size, &s);
357 if (size > (int)printunit) {
358 strncpy(chunk, sp, printunit);
359 chunk[printunit] = '\0';
360 DEBUGMSGTL((debugtoken, "\t%s\n", chunk));
362 DEBUGMSGTL((debugtoken, "\t%s\n", sp));
372 } /* end dump_chunk() */
377 /*******************************************************************-o-******
385 * Allocated memory pointing to a string of buflen char representing
386 * a printf'able form of the snmpEngineID.
388 * -OR- NULL on error.
391 * Translates the snmpEngineID TC into a printable string. From RFC 2271,
392 * Section 5 (pp. 36-37):
394 * First bit: 0 Bit string structured by means non-SNMPv3.
395 * 1 Structure described by SNMPv3 SnmpEngineID TC.
397 * Bytes 1-4: Enterprise ID. (High bit of first byte is ignored.)
399 * Byte 5: 0 (RESERVED by IANA.)
400 * 1 IPv4 address. ( 4 octets)
401 * 2 IPv6 address. ( 16 octets)
402 * 3 MAC address. ( 6 octets)
403 * 4 Locally defined text. (0-27 octets)
404 * 5 Locally defined octets. (0-27 octets)
405 * 6-127 (RESERVED for enterprise.)
407 * Bytes 6-32: (Determined by byte 5.)
410 * Non-printable characters are given in hex. Text is given in quotes.
411 * IP and MAC addresses are given in standard (UN*X) conventions. Sections
412 * are comma separated.
414 * esp, remaining_len and s trace the state of the constructed buffer.
415 * s will be defined if there is something to return, and it will point
416 * to the end of the constructed buffer.
419 * ASSUME "Text" means printable characters.
421 * XXX Must the snmpEngineID always have a minimum length of 12?
422 * (Cf. part 2 of the TC definition.)
423 * XXX Does not enforce upper-bound of 32 bytes.
424 * XXX Need a switch to decide whether to use DNS name instead of a simple
427 * FIX Use something other than sprint_hexstring which doesn't add
428 * trailing spaces and (sometimes embedded) newlines...
430 #ifdef CYGPKG_SNMPAGENT_V3_SUPPORT
431 #ifdef SNMP_TESTING_CODE
433 dump_snmpEngineID(const u_char *estring, size_t *estring_len)
435 #define eb(b) ( *(esp+b) & 0xff )
437 int rval = SNMPERR_SUCCESS,
442 char buf[SNMP_MAXBUF],
445 const u_char *esp = estring;
447 struct in_addr iaddr;
454 if ( !estring || (*estring_len <= 0) ) {
455 QUITFUN(SNMPERR_GENERR, dump_snmpEngineID_quit);
457 remaining_len = *estring_len;
458 memset(buf, 0, SNMP_MAXBUF);
463 * Test first bit. Return immediately with a hex string, or
464 * begin by formatting the enterprise ID.
466 if ( !(*esp & 0x80) ) {
467 sprint_hexstring(buf, esp, remaining_len);
468 s = strchr(buf, '\0');
470 goto dump_snmpEngineID_quit;
474 s += sprintf(s, "enterprise %d, ", ((*(esp+0)&0x7f) << 24) |
475 ((*(esp+1)&0xff) << 16) |
476 ((*(esp+2)&0xff) << 8) |
480 if (remaining_len < 5) { /* XXX Violating string. */
481 goto dump_snmpEngineID_quit;
484 esp += 4; /* Incremented one more in the switch below. */
490 * Act on the fifth byte.
492 switch ((int) *esp++) {
493 case 1: /* IPv4 address. */
495 if (remaining_len < 4) goto dump_snmpEngineID_violation;
496 memcpy(&iaddr.s_addr, esp, 4);
498 if ( !(t = inet_ntoa(iaddr)) ) goto dump_snmpEngineID_violation;
499 s += sprintf(s, "%s", t);
505 case 2: /* IPv6 address. */
507 if (remaining_len < 16) goto dump_snmpEngineID_violation;
510 "%02X%02X %02X%02X %02X%02X %02X%02X::"
511 "%02X%02X %02X%02X %02X%02X %02X%02X",
512 eb(0), eb(1), eb(2), eb(3),
513 eb(4), eb(5), eb(6), eb(7),
514 eb(8), eb(9), eb(10), eb(11),
515 eb(12), eb(13), eb(14), eb(15) );
521 case 3: /* MAC address. */
523 if (remaining_len < 6) goto dump_snmpEngineID_violation;
525 s += sprintf( s, "%02X:%02X:%02X:%02X:%02X:%02X",
526 eb(0), eb(1), eb(2), eb(3), eb(4), eb(5) );
534 /* Doesn't exist on all (many) architectures */
535 /* s += snprintf(s, remaining_len+3, "\"%s\"", esp); */
536 s += sprintf(s, "\"%s\"", esp);
537 goto dump_snmpEngineID_quit;
538 break; /*NOTREACHED*/
540 case 5: /* Octets. */
542 sprint_hexstring(s, esp, remaining_len);
543 s = strchr(buf, '\0');
545 goto dump_snmpEngineID_quit;
546 break; /*NOTREACHED*/
549 dump_snmpEngineID_violation:
550 case 0: /* Violation of RESERVED,
551 * -OR- of expected length.
554 s += sprintf(s, "!!! ");
556 default: /* Unknown encoding. */
558 if ( !gotviolation ) {
559 s += sprintf(s, "??? ");
561 sprint_hexstring(s, esp, remaining_len);
562 s = strchr(buf, '\0');
565 goto dump_snmpEngineID_quit;
572 * Cases 1-3 (IP and MAC addresses) should not have trailing
573 * octets, but perhaps they do. Throw them in too. XXX
575 if (remaining_len > 0) {
576 s += sprintf(s, " (??? ");
578 sprint_hexstring(s, esp, remaining_len);
579 s = strchr(buf, '\0');
582 s += sprintf(s, ")");
587 dump_snmpEngineID_quit:
591 memcpy(s, buf, (slen)-1);
594 memset(buf, 0, SNMP_MAXBUF); /* XXX -- Overkill? XXX: Yes! */
599 } /* end dump_snmpEngineID() */
600 #endif /* SNMP_TESTING_CODE */
601 #endif /* CYGPKG_SNMPAGENT_V3_SUPPORT */
605 * create a new time marker.
606 * NOTE: Caller must free time marker when no longer needed.
608 marker_t atime_newMarker(void)
610 marker_t pm = (marker_t)calloc(1,sizeof(struct timeval));
611 gettimeofday((struct timeval *)pm, 0);
618 void atime_setMarker(marker_t pm)
622 gettimeofday((struct timeval *)pm, 0);
626 * Test: Has (marked time plus delta) exceeded current time ?
627 * Returns 0 if test fails or cannot be tested (no marker).
629 int atime_ready( marker_t pm, int deltaT)
631 struct timeval txdelta, txnow;
634 memcpy((void *)&txdelta, pm, sizeof(txdelta));
635 while (deltaT > 1000) {
639 txdelta.tv_usec = (deltaT * 1000) + txdelta.tv_usec;
641 gettimeofday(&txnow, 0);
642 if (timercmp(&txnow, &txdelta, <))