]> git.stg.codes - ssmd.git/blob - 3rdparty/snmp++/src/v3.cpp
Initial adding
[ssmd.git] / 3rdparty / snmp++ / src / v3.cpp
1 /*_############################################################################
2   _## 
3   _##  v3.cpp  
4   _##
5   _##  SNMP++v3.2.25
6   _##  -----------------------------------------------
7   _##  Copyright (c) 2001-2010 Jochen Katz, Frank Fock
8   _##
9   _##  This software is based on SNMP++2.6 from Hewlett Packard:
10   _##  
11   _##    Copyright (c) 1996
12   _##    Hewlett-Packard Company
13   _##  
14   _##  ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15   _##  Permission to use, copy, modify, distribute and/or sell this software 
16   _##  and/or its documentation is hereby granted without fee. User agrees 
17   _##  to display the above copyright notice and this license notice in all 
18   _##  copies of the software and any documentation of the software. User 
19   _##  agrees to assume all liability for the use of the software; 
20   _##  Hewlett-Packard and Jochen Katz make no representations about the 
21   _##  suitability of this software for any purpose. It is provided 
22   _##  "AS-IS" without warranty of any kind, either express or implied. User 
23   _##  hereby grants a royalty-free license to any and all derivatives based
24   _##  upon this software code base. 
25   _##  
26   _##  Stuttgart, Germany, Thu Sep  2 00:07:47 CEST 2010 
27   _##  
28   _##########################################################################*/
29
30 char v3_cpp_version[]="#(@) SNMP++ $Id: v3.cpp 274 2006-11-03 19:21:16Z katz $";
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <string.h>
36 #ifndef _MSC_VER
37 #ifndef __BCPLUSPLUS__
38 #include <unistd.h>
39 #endif
40 #endif
41
42 #include "snmp_pp/log.h"
43 #include "snmp_pp/v3.h"
44 #include "snmp_pp/octet.h"
45
46 #ifdef SNMP_PP_NAMESPACE
47 namespace Snmp_pp {
48 #endif
49
50 #define MAX_LINE_LEN 100
51
52 const char *logfilename = NULL;
53 int debug_level = 19;
54
55 // Set the amount of log messages you want to get.
56 void debug_set_level(const int db_level)
57 {
58   debug_level = db_level;
59 }
60
61 #ifdef _DEBUG
62
63 void debughexcprintf(int db_level, const char *comment,
64                      const unsigned char *data, const unsigned int len)
65 {
66     if (db_level > debug_level) return;
67
68     char *buf = new char[MAX_LOG_SIZE];
69
70     if (NULL == buf) return;    // not good!
71
72     if (comment && (strlen(comment) < MAX_LOG_SIZE - 25))
73     {
74         sprintf(buf, "%s (length %i): \n", comment, len);
75         LOG_BEGIN(DEBUG_LOG | 3);
76         LOG(buf);
77         LOG_END;
78     }
79
80     char *tmp = new char[4];
81
82     if (NULL == tmp) { delete [] buf ; return; }
83
84     buf[0] = '\0';
85     for (unsigned int i=0; i<len; i++)
86     {
87         sprintf(tmp, "%02X ", data[i]);
88         strcat(buf, tmp);
89
90         if ((i+1)%4==0)
91         {
92             sprintf(tmp, " ");
93             strcat(buf, tmp);
94         }
95
96         if ((i+1)%16==0)
97         {
98             LOG_BEGIN(DEBUG_LOG | 3);
99             LOG(buf);
100             LOG_END;
101
102             // reset the buf
103             buf[0] = '\0';
104         }
105     }
106
107     if (buf[0] != '\0')
108     {
109         // print the last part of the message
110         LOG_BEGIN(DEBUG_LOG | 3);
111         LOG(buf);
112         LOG_END;
113     }
114
115     // and cleanup...
116     delete [] tmp;
117     delete [] buf;
118 }
119
120 void debugprintf(int db_level, const char *format, ...)
121 {
122     if (db_level > debug_level) return;
123
124     va_list  args;
125
126     va_start(args, format);
127
128 /////////////////////////////////////////////////////////////////
129 //      NOTE: This would be the best way to go (by using _vscprintf), 
130 //      but it is part of the VC7.0, and it can't be used in VC6.0
131 /////////////////////////////////////////////////////////////////
132         // _vscprintf doesn't count terminating '\0' so we add one more
133 //      int len = _vscprintf( format, args ) + 1;
134
135     char *buf = new char[MAX_LOG_SIZE];
136
137     if (NULL == buf) return; // not good!
138
139     vsprintf(buf, format, args);
140
141     va_end(args);
142
143     LOG_BEGIN(DEBUG_LOG | 1);
144     LOG(buf);
145     LOG_END;
146
147     // and cleanup...
148     delete [] buf;
149 }
150
151 #else
152 #if (defined (__STRICT_ANSI__) || !defined (__GNUC__)) && !defined (_MSC_VER)
153 void debugprintf(int, const char*, ...)
154 {
155 }
156 #endif
157
158 #endif
159
160 #ifdef _SNMPv3
161
162 unsigned char *v3strcpy(const unsigned char *src, const int srclen)
163 {
164   unsigned char *res = new unsigned char[srclen+1];
165   if (!res) return NULL;
166   memcpy(res, src, srclen);
167   res[srclen] = '\0';
168   return res;
169 }
170
171
172 int unsignedCharCompare(const unsigned char *str1, const long int ptr1len,
173                         const unsigned char *str2, const long int ptr2len)
174 {
175   if (ptr1len != ptr2len) return 0;
176
177   const unsigned char *ptr1 = str1;
178   const unsigned char *ptr2 = str2;
179
180   for (int i=0; i < ptr1len; ++i)
181     if (*ptr1++ != *ptr2++) return 0;
182
183   return 1;
184 }
185
186 // Encode the given string into the output buffer.
187 void encodeString(const unsigned char* in, const int in_length, char* out)
188 {
189   char* out_ptr = out;
190   const unsigned char* in_ptr = in;
191
192   for (int i=0; i<in_length; i++)
193   {
194     *out_ptr++ = 64 + ((*in_ptr >> 4) & 0xF);
195     *out_ptr++ = 64 + (*in_ptr++ & 0xF);
196   }
197 }
198
199 // Decode the given encoded string into the output buffer.
200 void decodeString(const unsigned char* in, const int in_length, char* out)
201 {
202   char* out_ptr = out;
203   const unsigned char* in_ptr = in;
204
205   if ((in_length % 2) || (in_length < 0))
206   {
207     LOG_BEGIN(WARNING_LOG | 3);
208     LOG("decodeString: Illegal input length (len)");
209     LOG(in_length);
210     LOG_END;
211
212     *out = 0;
213     return;
214   }
215
216   for (int i= in_length / 2; i > 0; i--)
217   {
218     *out_ptr = (*in_ptr++ & 0xF) << 4;
219     *out_ptr++ |= (*in_ptr++ & 0xF);
220   }
221   *out_ptr = 0; // make sure it is null terminated
222 }
223
224 // Read the bootCounter of the given engineID stored in the given file.
225 int getBootCounter(const char *fileName,
226                    const OctetStr &engineId, unsigned int &boot)
227 {
228   char line[MAX_LINE_LEN];
229   char encoded[MAXLENGTH_ENGINEID * 2 + 2];
230   int len = engineId.len();
231
232   FILE *file;
233
234   boot = 0;
235   file = fopen(fileName, "r");
236
237   if (!file)
238   {
239     LOG_BEGIN(ERROR_LOG | 1);
240     LOG("getBootCounter: Could not open (file)");
241     LOG(fileName);
242     LOG_END;
243
244     return SNMPv3_FILEOPEN_ERROR;
245   }
246
247   if (len > MAXLENGTH_ENGINEID)
248   {
249     LOG_BEGIN(ERROR_LOG | 3);
250     LOG("getBootCounter: engine id too long, ignoring last bytes (len) (max)");
251     LOG(len);
252     LOG(MAXLENGTH_ENGINEID);
253     LOG_END;
254
255     len = MAXLENGTH_ENGINEID;
256   }
257
258   encodeString(engineId.data(), len, encoded);
259   encoded[2*len]=' ';
260   encoded[2*len + 1] = 0;
261
262   while (fgets(line, MAX_LINE_LEN, file))
263   {
264     line[MAX_LINE_LEN - 1] = 0;
265     /* ignore comments */
266     if (line[0]=='#')
267       continue;
268
269     if (!strncmp(encoded, line, len*2 + 1))
270     {
271       /* line starts with engineId */
272       char* ptr = line;
273       /* skip until first space */
274       while (*ptr != 0 && *ptr != ' ')
275         ptr++;
276
277       if (*ptr == 0)
278       {
279         fclose(file);
280
281         LOG_BEGIN(ERROR_LOG | 3);
282         LOG("getBootCounter: Illegal line: (file) (line)");
283         LOG(fileName);
284         LOG(line);
285         LOG_END;
286
287         return SNMPv3_FILE_ERROR;
288       }
289       boot = atoi(ptr);
290       fclose(file);
291
292       LOG_BEGIN(DEBUG_LOG | 3);
293       LOG("getBootCounter: found entry (file) (engine id) (boot counter)");
294       LOG(fileName);
295       LOG(engineId.get_printable());
296       LOG(boot);
297       LOG_END;
298
299       return SNMPv3_OK;
300     }
301   }
302   fclose(file);
303
304   LOG_BEGIN(WARNING_LOG | 3);
305   LOG("getBootCounter: No entry found (file) (engine id)");
306   LOG(fileName);
307   LOG(engineId.get_printable());
308   LOG_END;
309
310   return SNMPv3_NO_ENTRY_ERROR;
311 }
312
313 // Store the bootCounter of the given engineID in the given file.
314 int saveBootCounter(const char *fileName,
315                     const OctetStr &engineId, const unsigned int boot)
316 {
317   char line[MAX_LINE_LEN];
318   char tmpFileName[MAXLENGTH_FILENAME];
319   char encoded[MAXLENGTH_ENGINEID * 2 + 2];
320   int found = FALSE;
321   int len = engineId.len();
322   FILE *file_in, *file_out;
323
324   tmpFileName[0] = 0;
325   sprintf(tmpFileName, "%s.tmp",fileName);
326   if (len > MAXLENGTH_ENGINEID)
327   {
328     LOG_BEGIN(ERROR_LOG | 3);
329     LOG("saveBootCounter: engine id too long, ignoring last bytes (len) (max)");
330     LOG(len);
331     LOG(MAXLENGTH_ENGINEID);
332     LOG_END;
333
334     len = MAXLENGTH_ENGINEID;
335   }
336
337   file_in = fopen(fileName, "r");
338   if (!file_in)
339   {
340     file_in = fopen(fileName, "w");
341     if (!file_in)
342     {
343       LOG_BEGIN(ERROR_LOG | 3);
344       LOG("saveBootCounter: could not create new file (file)");
345       LOG(fileName);
346       LOG_END;
347
348       return SNMPv3_FILECREATE_ERROR;
349     }
350
351     LOG_BEGIN(INFO_LOG | 3);
352     LOG("saveBootCounter: created new file (file)");
353     LOG(fileName);
354     LOG_END;
355
356     fputs("# \n",file_in);
357     fputs("# This file was created by an SNMP++v3 application,\n", file_in);
358     fputs("# it is used to store the snmpEngineBoots counters.\n", file_in);
359     fputs("# \n",file_in);
360     fputs("# Lines starting with '#' are comments.\n", file_in);
361     fputs("# The snmpEngineBoots counters are stored as\n", file_in);
362     fputs("# <encoded snmpEngineId> <bootCounter>\n", file_in);
363     fputs("# \n", file_in);
364     fclose(file_in);
365     file_in = fopen(fileName, "r");
366   }
367
368   file_out = fopen(tmpFileName, "w");
369
370   if ((file_in) && (file_out))
371   {
372     encodeString(engineId.data(), len, encoded);
373     encoded[len*2] = ' ';
374     encoded[len*2 + 1] = 0;
375
376     while (fgets(line, MAX_LINE_LEN, file_in))
377     {
378       line[MAX_LINE_LEN - 1] = 0;
379       if (!strncmp(encoded, line, len*2 + 1))
380       {
381         if (found)
382         {
383           LOG_BEGIN(WARNING_LOG | 3);
384           LOG("saveBootCounter: Removing doubled entry (file) (line)");
385           LOG(fileName);
386           LOG(line);
387           LOG_END;
388
389           continue;
390         }
391         sprintf(line,"%s%i\n", encoded, boot);
392         fputs(line, file_out);
393         found = TRUE;
394         continue;
395       }
396       fputs(line, file_out);
397     }
398     if (!found)
399     {
400       sprintf(line, "%s%i\n", encoded, boot);
401       fputs(line, file_out);
402     }
403     fclose(file_in);
404     fclose(file_out);
405 #ifdef WIN32
406     _unlink(fileName);
407 #endif
408     if (rename(tmpFileName, fileName))
409     {
410       LOG_BEGIN(ERROR_LOG | 1);
411       LOG("saveBootCounter: Failed to rename temporary file (tmp file) (file)");
412       LOG(tmpFileName);
413       LOG(fileName);
414       LOG_END;
415
416       return SNMPv3_FILERENAME_ERROR;
417     }
418
419     LOG_BEGIN(INFO_LOG | 5);
420     LOG("saveBootCounter: Saved counter (file) (engine id) (boot)");
421     LOG(fileName);
422     LOG(engineId.get_printable());
423     LOG(boot);
424     LOG_END;
425
426     return SNMPv3_OK;
427   }
428
429   LOG_BEGIN(ERROR_LOG | 1);
430   LOG("saveBootCounter: Failed to open both files (file) (tmp file)");
431   LOG(fileName);
432   LOG(tmpFileName);
433   LOG_END;
434
435   return SNMPv3_FILEOPEN_ERROR;
436 }
437
438 #endif
439
440 #ifdef SNMP_PP_NAMESPACE
441 }; // end of namespace Snmp_pp
442 #endif