tinydtls  0.8.6
dtls_debug.c
Go to the documentation of this file.
1 /*******************************************************************************
2  *
3  * Copyright (c) 2011, 2012, 2013, 2014, 2015 Olaf Bergmann (TZI) and others.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * and Eclipse Distribution License v. 1.0 which accompanies this distribution.
7  *
8  * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
9  * and the Eclipse Distribution License is available at
10  * http://www.eclipse.org/org/documents/edl-v10.php.
11  *
12  * Contributors:
13  * Olaf Bergmann - initial API and implementation
14  * Hauke Mehrtens - memory optimization, ECC integration
15  *
16  *******************************************************************************/
17 
18 #include "tinydtls.h"
19 
20 #if defined(HAVE_ASSERT_H) && !defined(assert)
21 #include <assert.h>
22 #endif
23 
24 #include <stdarg.h>
25 #include <stdio.h>
26 
27 #ifdef HAVE_ARPA_INET_H
28 #include <arpa/inet.h>
29 #endif
30 
31 #ifdef HAVE_TIME_H
32 #include <time.h>
33 #endif
34 
35 #include "global.h"
36 #include "dtls_debug.h"
37 
38 #ifndef min
39 #define min(a,b) ((a) < (b) ? (a) : (b))
40 #endif
41 
42 static int maxlog = DTLS_LOG_WARN; /* default maximum log level */
43 
44 const char *dtls_package_name() {
45  return PACKAGE_NAME;
46 }
47 
48 const char *dtls_package_version() {
49  return PACKAGE_VERSION;
50 }
51 
52 log_t
54  return maxlog;
55 }
56 
57 void
59 #ifdef NDEBUG
60  maxlog = min(level, DTLS_LOG_INFO);
61 #else /* !NDEBUG */
62  maxlog = level;
63 #endif /* NDEBUG */
64 }
65 
66 /* this array has the same order as the type log_t */
67 static char *loglevels[] = {
68  "EMRG", "ALRT", "CRIT", "WARN", "NOTE", "INFO", "DEBG"
69 };
70 
71 #ifdef HAVE_TIME_H
72 
73 static inline size_t
74 print_timestamp(char *s, size_t len, time_t t) {
75  struct tm *tmp;
76  tmp = localtime(&t);
77  return strftime(s, len, "%b %d %H:%M:%S", tmp);
78 }
79 
80 #else /* alternative implementation: just print the timestamp */
81 
82 static inline size_t
83 print_timestamp(char *s, size_t len, clock_time_t t) {
84 #ifdef HAVE_SNPRINTF
85  return snprintf(s, len, "%u.%03u",
86  (unsigned int)(t / CLOCK_SECOND),
87  (unsigned int)(t % CLOCK_SECOND));
88 #else /* HAVE_SNPRINTF */
89  /* @todo do manual conversion of timestamp */
90  return 0;
91 #endif /* HAVE_SNPRINTF */
92 }
93 
94 #endif /* HAVE_TIME_H */
95 
96 #ifndef NDEBUG
97 
106 static inline size_t
107 dtls_strnlen(const char *s, size_t maxlen) {
108  size_t n = 0;
109  while(*s++ && n < maxlen)
110  ++n;
111  return n;
112 }
113 
114 static size_t
115 dsrv_print_addr(const session_t *addr, char *buf, size_t len) {
116 #ifdef HAVE_ARPA_INET_H
117  const void *addrptr = NULL;
118  in_port_t port;
119  char *p = buf;
120 
121  switch (addr->addr.sa.sa_family) {
122  case AF_INET:
123  if (len < INET_ADDRSTRLEN)
124  return 0;
125 
126  addrptr = &addr->addr.sin.sin_addr;
127  port = ntohs(addr->addr.sin.sin_port);
128  break;
129  case AF_INET6:
130  if (len < INET6_ADDRSTRLEN + 2)
131  return 0;
132 
133  *p++ = '[';
134 
135  addrptr = &addr->addr.sin6.sin6_addr;
136  port = ntohs(addr->addr.sin6.sin6_port);
137 
138  break;
139  default:
140  memcpy(buf, "(unknown address type)", min(22, len));
141  return min(22, len);
142  }
143 
144  if (inet_ntop(addr->addr.sa.sa_family, addrptr, p, len) == 0) {
145  perror("dsrv_print_addr");
146  return 0;
147  }
148 
149  p += dtls_strnlen(p, len);
150 
151  if (addr->addr.sa.sa_family == AF_INET6) {
152  if (p < buf + len) {
153  *p++ = ']';
154  } else
155  return 0;
156  }
157 
158  p += snprintf(p, buf + len - p + 1, ":%d", port);
159 
160  return p - buf;
161 #else /* HAVE_ARPA_INET_H */
162 # if WITH_CONTIKI
163  char *p = buf;
164 # if NETSTACK_CONF_WITH_IPV6
165  uint8_t i;
166  const char hex[] = "0123456789ABCDEF";
167 
168  if (len < 41)
169  return 0;
170 
171  *p++ = '[';
172 
173  for (i=0; i < 16; i += 2) {
174  if (i) {
175  *p++ = ':';
176  }
177  *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
178  *p++ = hex[(addr->addr.u8[i] & 0x0f)];
179  *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
180  *p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
181  }
182  *p++ = ']';
183 # else /* NETSTACK_CONF_IPV6 */
184  if (len < 21)
185  return 0;
186 
187  p += sprintf(p, "%u.%u.%u.%u",
188  addr->addr.u8[0], addr->addr.u8[1],
189  addr->addr.u8[2], addr->addr.u8[3]);
190 # endif /* NETSTACK_CONF_IPV6 */
191  if (buf + len - p < 6)
192  return 0;
193 
194  p += sprintf(p, ":%d", uip_htons(addr->port));
195 
196  return p - buf;
197 # else /* WITH_CONTIKI */
198  /* TODO: output addresses manually */
199 # warning "inet_ntop() not available, network addresses will not be included in debug output"
200 # endif /* WITH_CONTIKI */
201  return 0;
202 #endif
203 }
204 
205 #endif /* NDEBUG */
206 
207 #ifndef WITH_CONTIKI
208 void
209 dsrv_log(log_t level, char *format, ...) {
210  static char timebuf[32];
211  va_list ap;
212  FILE *log_fd;
213 
214  if (maxlog < (int)level)
215  return;
216 
217  log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout;
218 
219  if (print_timestamp(timebuf,sizeof(timebuf), time(NULL)))
220  fprintf(log_fd, "%s ", timebuf);
221 
222  if (level <= DTLS_LOG_DEBUG)
223  fprintf(log_fd, "%s ", loglevels[level]);
224 
225  va_start(ap, format);
226  vfprintf(log_fd, format, ap);
227  va_end(ap);
228  fflush(log_fd);
229 }
230 #elif defined (HAVE_VPRINTF) /* WITH_CONTIKI */
231 void
232 dsrv_log(log_t level, char *format, ...) {
233  static char timebuf[32];
234  va_list ap;
235 
236  if (maxlog < level)
237  return;
238 
239  if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
240  PRINTF("%s ", timebuf);
241 
242  if (level <= DTLS_LOG_DEBUG)
243  PRINTF("%s ", loglevels[level]);
244 
245  va_start(ap, format);
246  vprintf(format, ap);
247  va_end(ap);
248 }
249 #endif /* WITH_CONTIKI */
250 
251 #ifndef NDEBUG
252 
253 void hexdump(const unsigned char *packet, int length) {
254  int n = 0;
255 
256  while (length--) {
257  if (n % 16 == 0)
258  printf("%08X ",n);
259 
260  printf("%02X ", *packet++);
261 
262  n++;
263  if (n % 8 == 0) {
264  if (n % 16 == 0)
265  printf("\n");
266  else
267  printf(" ");
268  }
269  }
270 }
271 
273 void dump(unsigned char *buf, size_t len) {
274  while (len--)
275  printf("%02x", *buf++);
276 }
277 
278 void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr)
279 {
280  char addrbuf[73];
281  int len;
282 
283  len = dsrv_print_addr(addr, addrbuf, sizeof(addrbuf));
284  if (!len)
285  return;
286  dsrv_log(level, "%s: %s\n", name, addrbuf);
287 }
288 
289 #ifndef WITH_CONTIKI
290 void
291 dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
292  static char timebuf[32];
293  FILE *log_fd;
294  int n = 0;
295 
296  if (maxlog < (int)level)
297  return;
298 
299  log_fd = level <= DTLS_LOG_CRIT ? stderr : stdout;
300 
301  if (print_timestamp(timebuf, sizeof(timebuf), time(NULL)))
302  fprintf(log_fd, "%s ", timebuf);
303 
304  if (level <= DTLS_LOG_DEBUG)
305  fprintf(log_fd, "%s ", loglevels[level]);
306 
307  if (extend) {
308  fprintf(log_fd, "%s: (%zu bytes):\n", name, length);
309 
310  while (length--) {
311  if (n % 16 == 0)
312  fprintf(log_fd, "%08X ", n);
313 
314  fprintf(log_fd, "%02X ", *buf++);
315 
316  n++;
317  if (n % 8 == 0) {
318  if (n % 16 == 0)
319  fprintf(log_fd, "\n");
320  else
321  fprintf(log_fd, " ");
322  }
323  }
324  } else {
325  fprintf(log_fd, "%s: (%zu bytes): ", name, length);
326  while (length--)
327  fprintf(log_fd, "%02X", *buf++);
328  }
329  fprintf(log_fd, "\n");
330 
331  fflush(log_fd);
332 }
333 #else /* WITH_CONTIKI */
334 void
335 dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend) {
336  static char timebuf[32];
337  int n = 0;
338 
339  if (maxlog < level)
340  return;
341 
342  if (print_timestamp(timebuf,sizeof(timebuf), clock_time()))
343  PRINTF("%s ", timebuf);
344 
345  if (level >= 0 && level <= DTLS_LOG_DEBUG)
346  PRINTF("%s ", loglevels[level]);
347 
348  if (extend) {
349  PRINTF("%s: (%zu bytes):\n", name, length);
350 
351  while (length--) {
352  if (n % 16 == 0)
353  PRINTF("%08X ", n);
354 
355  PRINTF("%02X ", *buf++);
356 
357  n++;
358  if (n % 8 == 0) {
359  if (n % 16 == 0)
360  PRINTF("\n");
361  else
362  PRINTF(" ");
363  }
364  }
365  } else {
366  PRINTF("%s: (%zu bytes): ", name, length);
367  while (length--)
368  PRINTF("%02X", *buf++);
369  }
370  PRINTF("\n");
371 }
372 #endif /* WITH_CONTIKI */
373 
374 #endif /* NDEBUG */
public tinydtls API
#define PACKAGE_VERSION
Definition: dtls_config.h:113
void dtls_set_log_level(log_t level)
Definition: dtls_debug.c:58
#define PACKAGE_NAME
Definition: dtls_config.h:101
log_t dtls_get_log_level()
Definition: dtls_debug.c:53
static char * loglevels[]
Definition: dtls_debug.c:67
uint32_t clock_time_t
Definition: dtls_time.h:46
#define PRINTF(...)
Definition: dtls_debug.h:49
static size_t print_timestamp(char *s, size_t len, time_t t)
Definition: dtls_debug.c:74
#define min(a, b)
Definition: dtls_debug.c:39
void dtls_dsrv_hexdump_log(log_t level, const char *name, const unsigned char *buf, size_t length, int extend)
Definition: dtls_debug.c:291
void dsrv_log(log_t level, char *format,...)
Definition: dtls_debug.c:209
#define CLOCK_SECOND
Definition: dtls_time.h:43
struct sockaddr sa
Definition: session.h:43
void dtls_dsrv_log_addr(log_t level, const char *name, const session_t *addr)
Definition: dtls_debug.c:278
static size_t dsrv_print_addr(const session_t *addr, char *buf, size_t len)
Definition: dtls_debug.c:115
union session_t::@2 addr
const char * dtls_package_name()
Definition: dtls_debug.c:44
static int maxlog
Definition: dtls_debug.c:42
log_t
Definition: dtls_debug.h:56
void hexdump(const unsigned char *packet, int length)
Definition: dtls_debug.c:253
unsigned char uint8_t
Definition: uthash.h:79
const char * dtls_package_version()
Definition: dtls_debug.c:48
struct sockaddr_in6 sin6
Definition: session.h:46
static size_t dtls_strnlen(const char *s, size_t maxlen)
Definition: dtls_debug.c:107
void dump(unsigned char *buf, size_t len)
Definition: dtls_debug.c:273
struct sockaddr_in sin
Definition: session.h:45