• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *    Copyright (c) 2017, The OpenThread Authors.
3  *    All rights reserved.
4  *
5  *    Redistribution and use in source and binary forms, with or without
6  *    modification, are permitted provided that the following conditions are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the distribution.
12  *    3. Neither the name of the copyright holder nor the
13  *       names of its contributors may be used to endorse or promote products
14  *       derived from this software without specific prior written permission.
15  *
16  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17  *    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  *    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  *    ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
20  *    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  *    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  *    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  *    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  *    POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #define OTBR_LOG_TAG "LOG"
30 
31 #ifndef OTBR_SYSLOG_FACILITY_ID
32 #define OTBR_SYSLOG_FACILITY_ID LOG_USER
33 #endif
34 
35 #include "common/logging.hpp"
36 
37 #include <assert.h>
38 #include <errno.h>
39 #include <stdarg.h>
40 #include <stdint.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <sys/time.h>
45 #include <syslog.h>
46 
47 #include <sstream>
48 
49 #include "common/code_utils.hpp"
50 #include "common/time.hpp"
51 
52 static otbrLogLevel sLevel            = OTBR_LOG_INFO;
53 static const char   sLevelString[][8] = {
54       "[EMERG]", "[ALERT]", "[CRIT]", "[ERR ]", "[WARN]", "[NOTE]", "[INFO]", "[DEBG]",
55 };
56 static bool sSyslogDisabled = false;
57 
58 static otbrLogLevel sDefaultLevel = OTBR_LOG_INFO;
59 
60 /** Get the current debug log level */
otbrLogGetLevel(void)61 otbrLogLevel otbrLogGetLevel(void)
62 {
63     return sLevel;
64 }
65 
66 /** Get the default log level */
otbrLogGetDefaultLevel(void)67 otbrLogLevel otbrLogGetDefaultLevel(void)
68 {
69     return sDefaultLevel;
70 }
71 
72 /**
73  * Set current log level.
74  */
otbrLogSetLevel(otbrLogLevel aLevel)75 void otbrLogSetLevel(otbrLogLevel aLevel)
76 {
77     assert(aLevel >= OTBR_LOG_EMERG && aLevel <= OTBR_LOG_DEBUG);
78     sLevel = aLevel;
79 }
80 
81 /** Enable/disable logging with syslog */
otbrLogSyslogSetEnabled(bool aEnabled)82 void otbrLogSyslogSetEnabled(bool aEnabled)
83 {
84     sSyslogDisabled = !aEnabled;
85 }
86 
87 /** Initialize logging */
otbrLogInit(const char * aProgramName,otbrLogLevel aLevel,bool aPrintStderr,bool aSyslogDisable)88 void otbrLogInit(const char *aProgramName, otbrLogLevel aLevel, bool aPrintStderr, bool aSyslogDisable)
89 {
90     const char *ident;
91 
92     assert(aProgramName != nullptr);
93     assert(aLevel >= OTBR_LOG_EMERG && aLevel <= OTBR_LOG_DEBUG);
94 
95     ident = strrchr(aProgramName, '/');
96     ident = (ident != nullptr) ? ident + 1 : aProgramName;
97 
98     otbrLogSyslogSetEnabled(!aSyslogDisable);
99 
100     if (!sSyslogDisabled)
101     {
102         openlog(ident, (LOG_CONS | LOG_PID) | (aPrintStderr ? LOG_PERROR : 0), OTBR_SYSLOG_FACILITY_ID);
103     }
104     sLevel        = aLevel;
105     sDefaultLevel = sLevel;
106 }
107 
GetPrefix(const char * aLogTag)108 static const char *GetPrefix(const char *aLogTag)
109 {
110     // Log prefix format : -xxx-----
111     const uint8_t kMaxTagSize = 7;
112     const uint8_t kBufferSize = kMaxTagSize + 3;
113     static char   prefix[kBufferSize];
114     uint8_t       tagLength = strlen(aLogTag) > kMaxTagSize ? kMaxTagSize : strlen(aLogTag);
115     int           index     = 0;
116 
117     if (strlen(aLogTag) > 0)
118     {
119         prefix[0] = '-';
120         memcpy(&prefix[1], aLogTag, tagLength);
121 
122         index = tagLength + 1;
123 
124         memset(&prefix[index], '-', kMaxTagSize - tagLength + 1);
125         index += kMaxTagSize - tagLength + 1;
126     }
127 
128     prefix[index++] = '\0';
129 
130     return prefix;
131 }
132 
133 /** log to the syslog or standard out */
otbrLog(otbrLogLevel aLevel,const char * aLogTag,const char * aFormat,...)134 void otbrLog(otbrLogLevel aLevel, const char *aLogTag, const char *aFormat, ...)
135 {
136     const uint16_t kBufferSize = 1024;
137     va_list        ap;
138     char           buffer[kBufferSize];
139 
140     va_start(ap, aFormat);
141 
142     if ((aLevel <= sLevel) && (vsnprintf(buffer, sizeof(buffer), aFormat, ap) > 0))
143     {
144         if (sSyslogDisabled)
145         {
146             printf("%s%s: %s\n", sLevelString[aLevel], GetPrefix(aLogTag), buffer);
147         }
148         else
149         {
150             syslog(static_cast<int>(aLevel), "%s%s: %s", sLevelString[aLevel], GetPrefix(aLogTag), buffer);
151         }
152     }
153 
154     va_end(ap);
155 
156     return;
157 }
158 
159 /** log to the syslog or standard out */
otbrLogv(otbrLogLevel aLevel,const char * aFormat,va_list aArgList)160 void otbrLogv(otbrLogLevel aLevel, const char *aFormat, va_list aArgList)
161 {
162     assert(aFormat);
163 
164     if (aLevel <= sLevel)
165     {
166         otbrLogvNoFilter(aLevel, aFormat, aArgList);
167     }
168 }
169 
170 /** log to the syslog or standard out */
otbrLogvNoFilter(otbrLogLevel aLevel,const char * aFormat,va_list aArgList)171 void otbrLogvNoFilter(otbrLogLevel aLevel, const char *aFormat, va_list aArgList)
172 {
173     if (sSyslogDisabled)
174     {
175         vprintf(aFormat, aArgList);
176         printf("\n");
177     }
178     else
179     {
180         vsyslog(static_cast<int>(aLevel), aFormat, aArgList);
181     }
182 }
183 
184 /** Hex dump data to the log */
otbrDump(otbrLogLevel aLevel,const char * aLogTag,const char * aPrefix,const void * aMemory,size_t aSize)185 void otbrDump(otbrLogLevel aLevel, const char *aLogTag, const char *aPrefix, const void *aMemory, size_t aSize)
186 {
187     static const char kHexChars[] = "0123456789abcdef";
188     assert(aPrefix && (aMemory || aSize == 0));
189     const uint8_t *pEnd;
190     const uint8_t *p8;
191     int            addr;
192 
193     if (aLevel >= sLevel)
194     {
195         return;
196     }
197 
198     /* break hex dumps into 16byte lines
199      * In the form ADDR: XX XX XX XX ...
200      */
201 
202     // we pre-increment... so subtract
203     addr = -16;
204 
205     while (aSize > 0)
206     {
207         size_t this_size;
208         char   hex[16 * 3 + 1];
209 
210         addr = addr + 16;
211         p8   = (const uint8_t *)(aMemory) + addr;
212 
213         /* truncate line to max 16 bytes */
214         this_size = aSize;
215         if (this_size > 16)
216         {
217             this_size = 16;
218         }
219         aSize = aSize - this_size;
220 
221         char *ch = hex - 1;
222 
223         for (pEnd = p8 + this_size; p8 < pEnd; p8++)
224         {
225             *++ch = kHexChars[(*p8) >> 4];
226             *++ch = kHexChars[(*p8) & 0x0f];
227             *++ch = ' ';
228         }
229         *ch = 0;
230 
231         otbrLog(aLevel, aLogTag, "%s: %04x: %s", aPrefix, addr, hex);
232     }
233 }
234 
otbrErrorString(otbrError aError)235 const char *otbrErrorString(otbrError aError)
236 {
237     const char *error;
238 
239     switch (aError)
240     {
241     case OTBR_ERROR_NONE:
242         error = "OK";
243         break;
244 
245     case OTBR_ERROR_ERRNO:
246         error = strerror(errno);
247         break;
248 
249     case OTBR_ERROR_DBUS:
250         error = "DBUS error";
251         break;
252 
253     case OTBR_ERROR_MDNS:
254         error = "MDNS error";
255         break;
256 
257     case OTBR_ERROR_OPENTHREAD:
258         error = "OpenThread error";
259         break;
260 
261     case OTBR_ERROR_NOT_FOUND:
262         error = "Not found";
263         break;
264 
265     case OTBR_ERROR_PARSE:
266         error = "Parse error";
267         break;
268 
269     case OTBR_ERROR_NOT_IMPLEMENTED:
270         error = "Not implemented";
271         break;
272 
273     case OTBR_ERROR_INVALID_ARGS:
274         error = "Invalid arguments";
275         break;
276 
277     case OTBR_ERROR_DUPLICATED:
278         error = "Duplicated";
279         break;
280 
281     case OTBR_ERROR_ABORTED:
282         error = "Aborted";
283         break;
284 
285     case OTBR_ERROR_INVALID_STATE:
286         error = "Invalid state";
287         break;
288 
289     default:
290         error = "Unknown";
291     }
292 
293     return error;
294 }
295 
otbrLogDeinit(void)296 void otbrLogDeinit(void)
297 {
298     closelog();
299 }
300