tinydtls  0.8.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
debug.c
Go to the documentation of this file.
1 /* debug.c -- debug utilities
2  *
3  * Copyright (C) 2011--2012 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * Permission is hereby granted, free of charge, to any person
6  * obtaining a copy of this software and associated documentation
7  * files (the "Software"), to deal in the Software without
8  * restriction, including without limitation the rights to use, copy,
9  * modify, merge, publish, distribute, sublicense, and/or sell copies
10  * of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be
14  * included in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25 
26 #include "tinydtls.h"
27 #include "dtls_config.h"
28 
29 #if defined(HAVE_ASSERT_H) && !defined(assert)
30 #include <assert.h>
31 #endif
32 
33 #include <stdarg.h>
34 #include <stdio.h>
35 
36 #ifdef HAVE_ARPA_INET_H
37 #include <arpa/inet.h>
38 #endif
39 
40 #ifdef HAVE_TIME_H
41 #include <time.h>
42 #endif
43 
44 #include "global.h"
45 #include "debug.h"
46 
47 static int maxlog = DTLS_LOG_WARN; /* default maximum log level */
48 
49 const char *dtls_package_name() {
50  return PACKAGE_NAME;
51 }
52 
53 const char *dtls_package_version() {
54  return PACKAGE_VERSION;
55 }
56 
57 log_t
59  return maxlog;
60 }
61 
62 void
64  maxlog = level;
65 }
66 
67 /* this array has the same order as the type log_t */
68 static char *loglevels[] = {
69  "EMRG", "ALRT", "CRIT", "WARN", "NOTE", "INFO", "DEBG"
70 };
71 
72 #ifdef HAVE_TIME_H
73 
74 static inline size_t
75 print_timestamp(char *s, size_t len, time_t t) {
76  struct tm *tmp;
77  tmp = localtime(&t);
78  return strftime(s, len, "%b %d %H:%M:%S", tmp);
79 }
80 
81 #else /* alternative implementation: just print the timestamp */
82 
83 static inline size_t
84 print_timestamp(char *s, size_t len, clock_time_t t) {
85 #ifdef HAVE_SNPRINTF
86  return snprintf(s, len, "%u.%03u",
87  (unsigned int)(t / CLOCK_SECOND),
88  (unsigned int)(t % CLOCK_SECOND));
89 #else /* HAVE_SNPRINTF */
90  /* @todo do manual conversion of timestamp */
91  return 0;
92 #endif /* HAVE_SNPRINTF */
93 }
94 
95 #endif /* HAVE_TIME_H */
96 
105 static inline size_t
106 dtls_strnlen(const char *s, size_t maxlen) {
107  size_t n = 0;
108  while(*s++ && n < maxlen)
109  ++n;
110  return n;
111 }
112 
113 #ifndef min
114 #define min(a,b) ((a) < (b) ? (a) : (b))
115 #endif
116 
117 static size_t
118 dsrv_print_addr(const session_t *addr, char *buf, size_t len) {
119 #ifdef HAVE_ARPA_INET_H
120  const void *addrptr = NULL;
121  in_port_t port;
122  char *p = buf;
123 
124  switch (addr->addr.sa.sa_family) {
125  case AF_INET:
126  if (len < INET_ADDRSTRLEN)
127  return 0;
128 
129  addrptr = &addr->addr.sin.sin_addr;
130  port = ntohs(addr->addr.sin.sin_port);
131  break;
132  case AF_INET6:
133  if (len < INET6_ADDRSTRLEN + 2)
134  return 0;
135 
136  *p++ = '[';
137 
138  addrptr = &addr->addr.sin6.sin6_addr;
139  port = ntohs(addr->addr.sin6.sin6_port);
140 
141  break;
142  default:
143  memcpy(buf, "(unknown address type)", min(22, len));
144  return min(22, len);
145  }
146 
147  if (inet_ntop(addr->addr.sa.sa_family, addrptr, p, len) == 0) {
148  perror("dsrv_print_addr");
149  return 0;
150  }
151 
152  p += dtls_strnlen(p, len);
153 
154  if (addr->addr.sa.sa_family == AF_INET6) {
155  if (p < buf + len) {
156  *p++ = ']';
157  } else
158  return 0;
159  }
160 
161  p += snprintf(p, buf + len - p + 1, ":%d", port);
162 
163  return p - buf;
164 #else /* HAVE_ARPA_INET_H */
165 # if WITH_CONTIKI
166  char *p = buf;
167 # ifdef UIP_CONF_IPV6
168  uint8_t i;
169  const char hex[] = "0123456789ABCDEF";
170 
171  if (len < 41)
172  return 0;
173 
174  *p++ = '[';
175 
176  for (i=0; i < 16; i += 2) {
177  if (i) {
178  *p++ = ':';
179  }
180  *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
181  *p++ = hex[(addr->addr.u8[i] & 0x0f)];
182  *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
183  *p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
184  }
185  *p++ = ']';
186 # else /* UIP_CONF_IPV6 */
187 # warning "IPv4 network addresses will not be included in debug output"
188 
189  if (len < 21)
190  return 0;
191 # endif /* UIP_CONF_IPV6 */
192  if (buf + len - p < 6)
193  return 0;
194 
195  p += sprintf(p, ":%d", uip_htons(addr->port));
196 
197  return p - buf;
198 # else /* WITH_CONTIKI */
199  /* TODO: output addresses manually */
200 # warning "inet_ntop() not available, network addresses will not be included in debug output"
201 # endif /* WITH_CONTIKI */
202  return 0;
203 #endif
204 }
205 
206 #ifndef WITH_CONTIKI
207 void
208 dsrv_log(log_t level, char *format, ...) {
209  static char timebuf[32];
210  va_list ap;
211  FILE *log_fd;
212 
213  if (maxlog < level)
214  return;
215 
216  log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout;
217 
218  if (print_timestamp(timebuf,sizeof(timebuf), time(NULL)))
219  fprintf(log_fd, "%s ", timebuf);
220 
221  if (level <= DTLS_LOG_DEBUG)
222  fprintf(log_fd, "%s ", loglevels[level]);
223 
224  va_start(ap, format);
225  vfprintf(log_fd, format, ap);
226  va_end(ap);
227  fflush(log_fd);
228 }
229 #elif defined (HAVE_VPRINTF) /* WITH_CONTIKI */
230 void
231 dsrv_log(log_t level, char *format, ...) {
232  static char timebuf[32];
233  va_list ap;
234 
235  if (maxlog < level)
236  return;
237 
238  if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
239  PRINTF("%s ", timebuf);
240 
241  if (level <= DTLS_LOG_DEBUG)
242  PRINTF("%s ", loglevels[level]);
243 
244  va_start(ap, format);
245  vprintf(format, ap);
246  va_end(ap);
247 }
248 #endif /* WITH_CONTIKI */
249 
250 #ifndef NDEBUG
251 
252 void hexdump(const unsigned char *packet, int length) {
253  int n = 0;
254 
255  while (length--) {
256  if (n % 16 == 0)
257  printf("%08X ",n);
258 
259  printf("%02X ", *packet++);
260 
261  n++;
262  if (n % 8 == 0) {
263  if (n % 16 == 0)
264  printf("\n");
265  else
266  printf(" ");
267  }
268  }
269 }
270 
272 void dump(unsigned char *buf, size_t len) {
273  while (len--)
274  printf("%02x", *buf++);
275 }
276 
277 void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr)
278 {
279  char addrbuf[73];
280  int len;
281 
282  len = dsrv_print_addr(addr, addrbuf, sizeof(addrbuf));
283  if (!len)
284  return;
285  dsrv_log(level, "%s: %s\n", name, addrbuf);
286 }
287 
288 #ifndef WITH_CONTIKI
289 void
290 dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
291  static char timebuf[32];
292  FILE *log_fd;
293  int n = 0;
294 
295  if (maxlog < level)
296  return;
297 
298  log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout;
299 
300  if (print_timestamp(timebuf, sizeof(timebuf), time(NULL)))
301  fprintf(log_fd, "%s ", timebuf);
302 
303  if (level <= DTLS_LOG_DEBUG)
304  fprintf(log_fd, "%s ", loglevels[level]);
305 
306  if (extend) {
307  fprintf(log_fd, "%s: (%zu bytes):\n", name, length);
308 
309  while (length--) {
310  if (n % 16 == 0)
311  fprintf(log_fd, "%08X ", n);
312 
313  fprintf(log_fd, "%02X ", *buf++);
314 
315  n++;
316  if (n % 8 == 0) {
317  if (n % 16 == 0)
318  fprintf(log_fd, "\n");
319  else
320  fprintf(log_fd, " ");
321  }
322  }
323  } else {
324  fprintf(log_fd, "%s: (%zu bytes): ", name, length);
325  while (length--)
326  fprintf(log_fd, "%02X", *buf++);
327  }
328  fprintf(log_fd, "\n");
329 
330  fflush(log_fd);
331 }
332 #else /* WITH_CONTIKI */
333 void
334 dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
335  static char timebuf[32];
336  int n = 0;
337 
338  if (maxlog < level)
339  return;
340 
341  if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
342  PRINTF("%s ", timebuf);
343 
344  if (level >= 0 && level <= DTLS_LOG_DEBUG)
345  PRINTF("%s ", loglevels[level]);
346 
347  if (extend) {
348  PRINTF("%s: (%zu bytes):\n", name, length);
349 
350  while (length--) {
351  if (n % 16 == 0)
352  PRINTF("%08X ", n);
353 
354  PRINTF("%02X ", *buf++);
355 
356  n++;
357  if (n % 8 == 0) {
358  if (n % 16 == 0)
359  PRINTF("\n");
360  else
361  PRINTF(" ");
362  }
363  }
364  } else {
365  PRINTF("%s: (%zu bytes): ", name, length);
366  while (length--)
367  PRINTF("%02X", *buf++);
368  }
369  PRINTF("\n");
370 }
371 #endif /* WITH_CONTIKI */
372 
373 #endif /* NDEBUG */
public tinydtls API
log_t
Definition: debug.h:66
static size_t print_timestamp(char *s, size_t len, time_t t)
Definition: debug.c:75
log_t dtls_get_log_level()
Definition: debug.c:58
static char * loglevels[]
Definition: debug.c:68
void dsrv_log(log_t level, char *format,...)
Definition: debug.c:208
void dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend)
Definition: debug.c:290
#define min(a, b)
Definition: debug.c:114
#define PRINTF(...)
Definition: debug.h:57
void dtls_set_log_level(log_t level)
Definition: debug.c:63
uint32_t clock_time_t
Definition: dtls_time.h:55
static size_t dsrv_print_addr(const session_t *addr, char *buf, size_t len)
Definition: debug.c:118
const char * dtls_package_version()
Definition: debug.c:53
#define PACKAGE_NAME
Definition: config.h:99
#define CLOCK_SECOND
Definition: dtls_time.h:52
void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr)
Definition: debug.c:277
struct sockaddr sa
Definition: session.h:52
static int maxlog
Definition: debug.c:47
union session_t::@2 addr
void dump(unsigned char *buf, size_t len)
Definition: debug.c:272
void hexdump(const unsigned char *packet, int length)
Definition: debug.c:252
static size_t dtls_strnlen(const char *s, size_t maxlen)
Definition: debug.c:106
#define PACKAGE_VERSION
Definition: config.h:111
struct sockaddr_in6 sin6
Definition: session.h:55
const char * dtls_package_name()
Definition: debug.c:49
struct sockaddr_in sin
Definition: session.h:54