1 /**
2  * @file library/tools.h
3  * @defgroup util Memory Utility Routines
4  * @ingroup library
5  * @{
6  *
7  * Portions of this file are copyrighted by:
8  * Copyright (c) 2016 VMware, Inc. All rights reserved.
9  * Use is subject to license terms specified in the COPYING file
10  * distributed with the Net-SNMP package.
11  */
12 
13 #ifndef _TOOLS_H
14 #define _TOOLS_H
15 
16 #ifdef __cplusplus
17 extern          "C" {
18 #endif
19 
20 
21 
22     /*
23      * General acros and constants.
24      */
25 #ifdef WIN32
26 #  define SNMP_MAXPATH MAX_PATH
27 #else
28 #  ifdef PATH_MAX
29 #    define SNMP_MAXPATH PATH_MAX
30 #  else
31 #    ifdef MAXPATHLEN
32 #      define SNMP_MAXPATH MAXPATHLEN
33 #    else
34 #      define SNMP_MAXPATH 1024		/* Should be safe enough */
35 #    endif
36 #  endif
37 #endif
38 
39 #define SNMP_MAXBUF		(1024 * 4)
40 #define SNMP_MAXBUF_MEDIUM	1024
41 #define SNMP_MAXBUF_SMALL	512
42 
43 #define SNMP_MAXBUF_MESSAGE	1500
44 
45 #define SNMP_MAXOID		64
46 #define SNMP_MAX_CMDLINE_OIDS	128
47 
48 #define SNMP_FILEMODE_CLOSED	0600
49 #define SNMP_FILEMODE_OPEN	0644
50 
51 #define BYTESIZE(bitsize)       ((bitsize + 7) >> 3)
52 #define ROUNDUP8(x)		( ( (x+7) >> 3 ) * 8 )
53 
54 #define SNMP_STRORNULL(x)       ( x ? x : "(null)")
55 
56 /** @def SNMP_FREE(s)
57     Frees a pointer only if it is !NULL and sets its value to NULL */
58 #define SNMP_FREE(s)    do { if (s) { free((void *)s); s=NULL; } } while(0)
59 
60 /** @def SNMP_SWIPE_MEM(n, s)
61     Frees pointer n only if it is !NULL, sets n to s and sets s to NULL */
62 #define SNMP_SWIPE_MEM(n,s) do { if (n) free((void *)n); n = s; s=NULL; } while(0)
63 
64     /*
65      * XXX Not optimal everywhere.
66      */
67 /** @def SNMP_MALLOC_STRUCT(s)
68     Mallocs memory of sizeof(struct s), zeros it and returns a pointer to it. */
69 #define SNMP_MALLOC_STRUCT(s)   (struct s *) calloc(1, sizeof(struct s))
70 
71 /** @def SNMP_MALLOC_TYPEDEF(t)
72     Mallocs memory of sizeof(t), zeros it and returns a pointer to it. */
73 #define SNMP_MALLOC_TYPEDEF(td)  (td *) calloc(1, sizeof(td))
74 
75 /** @def SNMP_ZERO(s,l)
76     Zeros l bytes of memory starting at s. */
77 #define SNMP_ZERO(s,l)	do { if (s) memset(s, 0, l); } while(0)
78 
79 
80 /**
81  * @def NETSNMP_REMOVE_CONST(t, e)
82  *
83  * Cast away constness without that gcc -Wcast-qual prints a compiler warning,
84  * similar to const_cast<> in C++.
85  *
86  * @param[in] t A pointer type.
87  * @param[in] e An expression of a type that can be assigned to the type (const t).
88  */
89 #if defined(__GNUC__)
90 #define NETSNMP_REMOVE_CONST(t, e)                                      \
91     (__extension__ ({ const t tmp = (e); (t)(size_t)tmp; }))
92 #else
93 #define NETSNMP_REMOVE_CONST(t, e) ((t)(size_t)(e))
94 #endif
95 
96 
97 #define TOUPPER(c)	(c >= 'a' && c <= 'z' ? c - ('a' - 'A') : c)
98 #define TOLOWER(c)	(c >= 'A' && c <= 'Z' ? c + ('a' - 'A') : c)
99 
100 #define HEX2VAL(s) \
101 	((isalpha(s) ? (TOLOWER(s)-'a'+10) : (TOLOWER(s)-'0')) & 0xf)
102 #define VAL2HEX(s)	( (s) + (((s) >= 10) ? ('a'-10) : '0') )
103 
104 
105 /** @def SNMP_MAX(a, b)
106     Computers the maximum of a and b. */
107 #define SNMP_MAX(a,b) ((a) > (b) ? (a) : (b))
108 
109 /** @def SNMP_MIN(a, b)
110     Computers the minimum of a and b. */
111 #define SNMP_MIN(a,b) ((a) > (b) ? (b) : (a))
112 
113 /** @def SNMP_MACRO_VAL_TO_STR(s)
114  *  Expands to string with value of the s.
115  *  If s is macro, the resulting string is value of the macro.
116  *  Example:
117  *   \#define TEST 1234
118  *   SNMP_MACRO_VAL_TO_STR(TEST) expands to "1234"
119  *   SNMP_MACRO_VAL_TO_STR(TEST+1) expands to "1234+1"
120  */
121 #define SNMP_MACRO_VAL_TO_STR(s) SNMP_MACRO_VAL_TO_STR_PRIV(s)
122 #define SNMP_MACRO_VAL_TO_STR_PRIV(s) #s
123 
124 #ifndef FALSE
125 #define FALSE 0
126 #endif
127 #ifndef TRUE
128 #define TRUE  1
129 #endif
130 
131 #define NETSNMP_IGNORE_RESULT(e) do { if (e) { } } while (0)
132 
133     /*
134      * QUIT the FUNction:
135      *      e       Error code variable
136      *      l       Label to goto to cleanup and get out of the function.
137      *
138      * XXX  It would be nice if the label could be constructed by the
139      *      preprocessor in context.  Limited to a single error return value.
140      *      Temporary hack at best.
141      */
142 #define QUITFUN(e, l)			\
143 	if ( (e) != SNMPERR_SUCCESS) {	\
144 		rval = SNMPERR_GENERR;	\
145 		goto l ;		\
146 	}
147 
148 /**
149  * Compute res = a + b.
150  *
151  * @pre a and b must be normalized 'struct timeval' values.
152  *
153  * @note res may be the same variable as one of the operands. In other
154  *   words, &a == &res || &b == &res may hold.
155  */
156 #define NETSNMP_TIMERADD(a, b, res) do {             \
157     (res)->tv_sec  = (a)->tv_sec  + (b)->tv_sec;     \
158     (res)->tv_usec = (a)->tv_usec + (b)->tv_usec;    \
159     if ((res)->tv_usec >= 1000000L) {                \
160         (res)->tv_usec -= 1000000L;                  \
161         (res)->tv_sec++;                             \
162     }                                                \
163 } while (0)
164 
165 /**
166  * Compute res = a - b.
167  *
168  * @pre a and b must be normalized 'struct timeval' values.
169  *
170  * @note res may be the same variable as one of the operands. In other
171  *   words, &a == &res || &b == &res may hold.
172  */
173 #define NETSNMP_TIMERSUB(a, b, res) do {                        \
174     (res)->tv_sec  = (a)->tv_sec  - (b)->tv_sec - 1;            \
175     (res)->tv_usec = (a)->tv_usec - (b)->tv_usec + 1000000L;    \
176     if ((res)->tv_usec >= 1000000L) {                           \
177         (res)->tv_usec -= 1000000L;                             \
178         (res)->tv_sec++;                                        \
179     }                                                           \
180 } while (0)
181 
182 #define ENGINETIME_MAX	2147483647      /* ((2^31)-1) */
183 #define ENGINEBOOT_MAX	2147483647      /* ((2^31)-1) */
184 
185 
186     struct timeval;
187 
188 
189     /*
190      * Prototypes.
191      */
192 
193     NETSNMP_IMPORT
194     int             snmp_realloc(u_char ** buf, size_t * buf_len);
195 
196     void            free_zero(void *buf, size_t size);
197 
198     u_char         *malloc_random(size_t * size);
199     u_char         *malloc_zero(size_t size);
200     NETSNMP_IMPORT
201     void           *netsnmp_memdup(const void * from, size_t size);
202     NETSNMP_IMPORT
203     void *netsnmp_memdup_nt(const void *from, size_t from_len, size_t *to_len);
204 
205     void            netsnmp_check_definedness(const void *packet,
206                                               size_t length);
207 
208     NETSNMP_IMPORT
209     u_int           netsnmp_binary_to_hex(u_char ** dest, size_t *dest_len,
210                                           int allow_realloc,
211                                           const u_char * input, size_t len);
212 
213     NETSNMP_IMPORT
214     u_int           binary_to_hex(const u_char * input, size_t len,
215                                   char **output);
216                     /* preferred */
217     int             netsnmp_hex_to_binary(u_char ** buf, size_t * buf_len,
218                                          size_t * offset, int allow_realloc,
219                                          const char *hex, const char *delim);
220                     /* calls netsnmp_hex_to_binary w/delim of " " */
221     NETSNMP_IMPORT
222     int             snmp_hex_to_binary(u_char ** buf, size_t * buf_len,
223                                        size_t * offset, int allow_realloc,
224                                        const char *hex);
225                     /* handles odd lengths */
226     NETSNMP_IMPORT
227     int             hex_to_binary2(const u_char * input, size_t len,
228                                    char **output);
229 
230     NETSNMP_IMPORT
231     int             snmp_decimal_to_binary(u_char ** buf, size_t * buf_len,
232                                            size_t * out_len,
233                                            int allow_realloc,
234                                            const char *decimal);
235 #define snmp_cstrcat(b,l,o,a,s) snmp_strcat(b,l,o,a,(const u_char *)s)
236     NETSNMP_IMPORT
237     int             snmp_strcat(u_char ** buf, size_t * buf_len,
238                                 size_t * out_len, int allow_realloc,
239                                 const u_char * s);
240     NETSNMP_IMPORT
241     char           *netsnmp_strdup_and_null(const u_char * from,
242                                             size_t from_len);
243 
244     NETSNMP_IMPORT
245     void            dump_chunk(const char *debugtoken, const char *title,
246                                const u_char * buf, int size);
247     char           *dump_snmpEngineID(const u_char * buf, size_t * buflen);
248 
249     /** A pointer to an opaque time marker value. */
250     typedef void   *marker_t;
251     typedef const void* const_marker_t;
252 
253     NETSNMP_IMPORT
254     marker_t        atime_newMarker(void);
255     NETSNMP_IMPORT
256     void            atime_setMarker(marker_t pm);
257     NETSNMP_IMPORT
258     void            netsnmp_get_monotonic_clock(struct timeval* tv);
259     NETSNMP_IMPORT
260     void            netsnmp_set_monotonic_marker(marker_t *pm);
261     NETSNMP_IMPORT
262     long            atime_diff(const_marker_t first, const_marker_t second);
263     NETSNMP_IMPORT
264     u_long          uatime_diff(const_marker_t first, const_marker_t second);       /* 1/1000th sec */
265     NETSNMP_IMPORT
266     u_long          uatime_hdiff(const_marker_t first, const_marker_t second);      /* 1/100th sec */
267     NETSNMP_IMPORT
268     int             atime_ready(const_marker_t pm, int delta_ms);
269     NETSNMP_IMPORT
270     int             netsnmp_ready_monotonic(const_marker_t pm, int delta_ms);
271     int             uatime_ready(const_marker_t pm, unsigned int delta_ms);
272 
273     int             marker_tticks(const_marker_t pm);
274     int             timeval_tticks(const struct timeval *tv);
275     NETSNMP_IMPORT
276     char            *netsnmp_getenv(const char *name);
277     NETSNMP_IMPORT
278     int             netsnmp_setenv(const char *envname, const char *envval,
279                                    int overwrite);
280 
281     int             netsnmp_addrstr_hton(char *ptr, size_t len);
282 
283     NETSNMP_IMPORT
284     int             netsnmp_string_time_to_secs(const char *time_string);
285 
286 #ifdef __cplusplus
287 }
288 #endif
289 #endif                          /* _TOOLS_H */
290 /* @} */
291