libcoap  4.1.2
coap_io.c
Go to the documentation of this file.
1 /* coap_io.h -- Default network I/O functions for libcoap
2  *
3  * Copyright (C) 2012,2014 Olaf Bergmann <bergmann@tzi.org>
4  *
5  * This file is part of the CoAP library libcoap. Please see
6  * README for terms of use.
7  */
8 
9 #include "coap_config.h"
10 
11 #ifdef HAVE_STDIO_H
12 # include <stdio.h>
13 #endif
14 
15 #ifdef HAVE_SYS_SELECT_H
16 # include <sys/select.h>
17 #endif
18 #ifdef HAVE_SYS_SOCKET_H
19 # include <sys/socket.h>
20 #endif
21 #ifdef HAVE_NETINET_IN_H
22 # include <netinet/in.h>
23 #endif
24 #ifdef HAVE_SYS_UIO_H
25 # include <sys/uio.h>
26 #endif
27 #ifdef HAVE_UNISTD_H
28 # include <unistd.h>
29 #endif
30 #include <errno.h>
31 
32 #ifdef WITH_CONTIKI
33 # include "uip.h"
34 #endif
35 
36 #include "debug.h"
37 #include "mem.h"
38 #include "coap_io.h"
39 
40 #ifdef WITH_POSIX
41 struct coap_packet_t {
46 
47  int ifindex;
48  void *session;
50  size_t length;
51  unsigned char payload[];
52 };
53 #endif
54 
55 #ifndef CUSTOM_COAP_NETWORK_ENDPOINT
56 
57 #ifdef WITH_CONTIKI
58 static int ep_initialized = 0;
59 
60 static inline struct coap_endpoint_t *
61 coap_malloc_contiki_endpoint() {
62  static struct coap_endpoint_t ep;
63 
64  if (ep_initialized) {
65  return NULL;
66  } else {
67  ep_initialized = 1;
68  return &ep;
69  }
70 }
71 
72 static inline void
73 coap_free_contiki_endpoint(struct coap_endpoint_t *ep) {
74  ep_initialized = 0;
75 }
76 
79  struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint();
80 
81  if (ep) {
82  memset(ep, 0, sizeof(struct coap_endpoint_t));
83  ep->handle.conn = udp_new(NULL, 0, NULL);
84 
85  if (!ep->handle.conn) {
87  return NULL;
88  }
89 
90  coap_address_init(&ep->addr);
91  uip_ipaddr_copy(&ep->addr.addr, &addr->addr);
92  ep->addr.port = addr->port;
93  udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port);
94  }
95  return ep;
96 }
97 
98 void
100  if (ep) {
101  if (ep->handle.conn) {
102  uip_udp_remove((struct uip_udp_conn *)ep->handle.conn);
103  }
104  coap_free_contiki_endpoint(ep);
105  }
106 }
107 
108 #else /* WITH_CONTIKI */
109 static inline struct coap_endpoint_t *
111  return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t));
112 }
113 
114 static inline void
116  coap_free(ep);
117 }
118 
121  int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0);
122  int on = 1;
123  struct coap_endpoint_t *ep;
124 
125  if (sockfd < 0) {
126  coap_log(LOG_WARNING, "coap_new_endpoint: socket");
127  return NULL;
128  }
129 
130  if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
131  coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR");
132 
133  on = 1;
134  switch(addr->addr.sa.sa_family) {
135  case AF_INET:
136  if (setsockopt(sockfd, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on)) < 0)
137  coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IP_PKTINFO\n");
138  break;
139  case AF_INET6:
140 #ifdef IPV6_RECVPKTINFO
141  if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0)
142  coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_RECVPKTINFO\n");
143 #else /* IPV6_RECVPKTINFO */
144  if (setsockopt(sockfd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0)
145  coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_PKTINFO\n");
146 #endif /* IPV6_RECVPKTINFO */
147  break;
148  default:
149  coap_log(LOG_ALERT, "coap_new_endpoint: unsupported sa_family\n");
150  }
151 
152  if (bind(sockfd, &addr->addr.sa, addr->size) < 0) {
153  coap_log(LOG_WARNING, "coap_new_endpoint: bind");
154  close (sockfd);
155  return NULL;
156  }
157 
159  if (!ep) {
160  coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
161  close(sockfd);
162  return NULL;
163  }
164 
165  memset(ep, 0, sizeof(struct coap_endpoint_t));
166  ep->handle.fd = sockfd;
167  ep->flags = flags;
168 
169  ep->addr.size = addr->size;
170  if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) {
171  coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address");
172  close (sockfd);
173  return NULL;
174  }
175 
176 #ifndef NDEBUG
177  if (LOG_DEBUG <= coap_get_log_level()) {
178 #ifndef INET6_ADDRSTRLEN
179 #define INET6_ADDRSTRLEN 40
180 #endif
181  unsigned char addr_str[INET6_ADDRSTRLEN+8];
182 
183  if (coap_print_addr(&ep->addr, addr_str, INET6_ADDRSTRLEN+8)) {
184  debug("created %sendpoint %s\n",
185  ep->flags & COAP_ENDPOINT_DTLS ? "DTLS " : "",
186  addr_str);
187  }
188  }
189 #endif /* NDEBUG */
190 
191  return (coap_endpoint_t *)ep;
192 }
193 
194 void
196  if(ep) {
197  if (ep->handle.fd >= 0)
198  close(ep->handle.fd);
200  }
201 }
202 
203 #endif /* WITH_CONTIKI */
204 #endif /* CUSTOM_COAP_NETWORK_ENDPOINT */
205 
206 #ifndef CUSTOM_COAP_NETWORK_SEND
207 
208 #if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H)
209 /* define struct in6_pktinfo and struct in_pktinfo if not available
210  FIXME: check with configure
211 */
212 struct in6_pktinfo {
213  struct in6_addr ipi6_addr; /* src/dst IPv6 address */
214  unsigned int ipi6_ifindex; /* send/recv interface index */
215 };
216 
217 struct in_pktinfo {
219  struct in_addr ipi_spec_dst;
220  struct in_addr ipi_addr;
221 };
222 #endif
223 
224 #if defined(WITH_POSIX) && !defined(SOL_IP)
225 /* Solaris expects level IPPROTO_IP for ancillary data. */
226 #define SOL_IP IPPROTO_IP
227 #endif
228 
229 #ifdef __GNUC__
230 #define UNUSED_PARAM __attribute__ ((unused))
231 #else /* not a GCC */
232 #define UNUSED_PARAM
233 #endif /* GCC */
234 
235 ssize_t
237  const coap_endpoint_t *local_interface,
238  const coap_address_t *dst,
239  unsigned char *data,
240  size_t datalen) {
241 
242  struct coap_endpoint_t *ep =
243  (struct coap_endpoint_t *)local_interface;
244 
245 #ifndef WITH_CONTIKI
246  /* a buffer large enough to hold all protocol address types */
247  char buf[CMSG_LEN(sizeof(struct sockaddr_storage))];
248  struct msghdr mhdr;
249  struct iovec iov[1];
250 
251  assert(local_interface);
252 
253  iov[0].iov_base = data;
254  iov[0].iov_len = datalen;
255 
256  memset(&mhdr, 0, sizeof(struct msghdr));
257  mhdr.msg_name = (void *)&dst->addr;
258  mhdr.msg_namelen = dst->size;
259 
260  mhdr.msg_iov = iov;
261  mhdr.msg_iovlen = 1;
262 
263  switch (dst->addr.sa.sa_family) {
264  case AF_INET6: {
265  struct cmsghdr *cmsg;
266  struct in6_pktinfo *pktinfo;
267 
268  mhdr.msg_control = buf;
269  mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
270 
271  cmsg = CMSG_FIRSTHDR(&mhdr);
272  cmsg->cmsg_level = IPPROTO_IPV6;
273  cmsg->cmsg_type = IPV6_PKTINFO;
274  cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
275 
276  pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
277  memset(pktinfo, 0, sizeof(struct in6_pktinfo));
278 
279  pktinfo->ipi6_ifindex = ep->ifindex;
280  if (coap_is_mcast(&local_interface->addr)) {
281  /* We cannot send with multicast address as source address
282  * and hence let the kernel pick the outgoing interface. */
283  pktinfo->ipi6_ifindex = 0;
284  memset(&pktinfo->ipi6_addr, 0, sizeof(pktinfo->ipi6_addr));
285  } else {
286  pktinfo->ipi6_ifindex = ep->ifindex;
287  memcpy(&pktinfo->ipi6_addr,
288  &local_interface->addr.addr.sin6.sin6_addr,
289  local_interface->addr.size);
290  }
291  break;
292  }
293  case AF_INET: {
294  struct cmsghdr *cmsg;
295  struct in_pktinfo *pktinfo;
296 
297  mhdr.msg_control = buf;
298  mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
299 
300  cmsg = CMSG_FIRSTHDR(&mhdr);
301  cmsg->cmsg_level = SOL_IP;
302  cmsg->cmsg_type = IP_PKTINFO;
303  cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
304 
305  pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
306  memset(pktinfo, 0, sizeof(struct in_pktinfo));
307 
308  if (coap_is_mcast(&local_interface->addr)) {
309  /* We cannot send with multicast address as source address
310  * and hence let the kernel pick the outgoing interface. */
311  pktinfo->ipi_ifindex = 0;
312  memset(&pktinfo->ipi_spec_dst, 0, sizeof(pktinfo->ipi_spec_dst));
313  } else {
314  pktinfo->ipi_ifindex = ep->ifindex;
315  memcpy(&pktinfo->ipi_spec_dst,
316  &local_interface->addr.addr.sin.sin_addr,
317  local_interface->addr.size);
318  }
319  break;
320  }
321  default:
322  /* error */
323  coap_log(LOG_WARNING, "protocol not supported\n");
324  return -1;
325  }
326 
327  return sendmsg(ep->handle.fd, &mhdr, 0);
328 #else /* WITH_CONTIKI */
329  /* FIXME: untested */
330  /* FIXME: is there a way to check if send was successful? */
331  uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen,
332  &dst->addr, dst->port);
333  return datalen;
334 #endif /* WITH_CONTIKI */
335 }
336 
337 #endif /* CUSTOM_COAP_NETWORK_SEND */
338 
339 #ifndef CUSTOM_COAP_NETWORK_READ
340 
341 #define SIN6(A) ((struct sockaddr_in6 *)(A))
342 
343 #ifdef WITH_POSIX
344 static coap_packet_t *
346  coap_packet_t *packet;
347  const size_t need = sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE;
348 
349  packet = (coap_packet_t *)coap_malloc(need);
350  if (packet) {
351  memset(packet, 0, need);
352  }
353  return packet;
354 }
355 
356 void
358  coap_free(packet);
359 }
360 #endif /* WITH_POSIX */
361 #ifdef WITH_CONTIKI
362 static inline coap_packet_t *
363 coap_malloc_packet(void) {
365 }
366 
367 void
369  coap_free_type(COAP_PACKET, packet);
370 }
371 #endif /* WITH_CONTIKI */
372 
373 static inline size_t
375  return COAP_MAX_PDU_SIZE;
376 }
377 
378 void
380 {
381  target->handle = packet->interface->handle;
382  memcpy(&target->addr, &packet->dst, sizeof(target->addr));
383  target->ifindex = packet->ifindex;
384  target->flags = 0; /* FIXME */
385 }
386 void
388 {
389  memcpy(target, &packet->src, sizeof(coap_address_t));
390 }
391 void
392 coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
393 {
394  *address = packet->payload;
395  *length = packet->length;
396 }
397 
403 static inline int
405  return coap_address_isany(local) || coap_address_equals(dst, local) ||
406  coap_is_mcast(dst);
407 }
408 
409 ssize_t
411  ssize_t len = -1;
412 
413 #ifdef WITH_POSIX
414  char msg_control[CMSG_LEN(sizeof(struct sockaddr_storage))];
415  struct msghdr mhdr;
416  struct iovec iov[1];
417 #endif /* WITH_POSIX */
418 
419  assert(ep);
420  assert(packet);
421 
422  *packet = coap_malloc_packet();
423 
424  if (!*packet) {
425  warn("coap_network_read: insufficient memory, drop packet\n");
426  return -1;
427  }
428 
429  coap_address_init(&(*packet)->dst); /* the local interface address */
430  coap_address_init(&(*packet)->src); /* the remote peer */
431 
432 #ifdef WITH_POSIX
433  iov[0].iov_base = (*packet)->payload;
434  iov[0].iov_len = coap_get_max_packetlength(*packet);
435 
436  memset(&mhdr, 0, sizeof(struct msghdr));
437 
438  mhdr.msg_name = &(*packet)->src.addr.st;
439  mhdr.msg_namelen = sizeof((*packet)->src.addr.st);
440 
441  mhdr.msg_iov = iov;
442  mhdr.msg_iovlen = 1;
443 
444  mhdr.msg_control = msg_control;
445  mhdr.msg_controllen = sizeof(msg_control);
446  assert(sizeof(msg_control) == CMSG_LEN(sizeof(struct sockaddr_storage)));
447 
448  len = recvmsg(ep->handle.fd, &mhdr, 0);
449 
450  if (len < 0) {
451  coap_log(LOG_WARNING, "coap_network_read: %s\n", strerror(errno));
452  goto error;
453  } else {
454  struct cmsghdr *cmsg;
455 
456  coap_log(LOG_DEBUG, "received %d bytes on fd %d\n", (int)len, ep->handle.fd);
457 
458  /* use getsockname() to get the local port */
459  (*packet)->dst.size = sizeof((*packet)->dst.addr);
460  if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) {
461  coap_log(LOG_DEBUG, "cannot determine local port\n");
462  goto error;
463  }
464 
465  (*packet)->length = len;
466 
467  /* Walk through ancillary data records until the local interface
468  * is found where the data was received. */
469  for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
470 
471  /* get the local interface for IPv6 */
472  if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
473  union {
474  unsigned char *c;
475  struct in6_pktinfo *p;
476  } u;
477  u.c = CMSG_DATA(cmsg);
478  (*packet)->ifindex = (int)(u.p->ipi6_ifindex);
479 
480  memcpy(&(*packet)->dst.addr.sin6.sin6_addr,
481  &u.p->ipi6_addr, sizeof(struct in6_addr));
482 
483  (*packet)->src.size = mhdr.msg_namelen;
484  assert((*packet)->src.size == sizeof(struct sockaddr_in6));
485 
486  (*packet)->src.addr.sin6.sin6_family = SIN6(mhdr.msg_name)->sin6_family;
487  (*packet)->src.addr.sin6.sin6_addr = SIN6(mhdr.msg_name)->sin6_addr;
488  (*packet)->src.addr.sin6.sin6_port = SIN6(mhdr.msg_name)->sin6_port;
489 
490  break;
491  }
492 
493  /* local interface for IPv4 */
494  if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
495  union {
496  unsigned char *c;
497  struct in_pktinfo *p;
498  } u;
499 
500  u.c = CMSG_DATA(cmsg);
501  (*packet)->ifindex = u.p->ipi_ifindex;
502 
503  memcpy(&(*packet)->dst.addr.sin.sin_addr,
504  &u.p->ipi_addr, sizeof(struct in_addr));
505 
506  (*packet)->src.size = mhdr.msg_namelen;
507  memcpy(&(*packet)->src.addr.st, mhdr.msg_name, (*packet)->src.size);
508 
509  break;
510  }
511  }
512 
513  if (!is_local_if(&ep->addr, &(*packet)->dst)) {
514  coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
515  goto error;
516  }
517  }
518 #endif /* WITH_POSIX */
519 #ifdef WITH_CONTIKI
520  /* FIXME: untested, make this work */
521 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
522 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
523 
524  if(uip_newdata()) {
525  uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr);
526  (*packet)->src.port = UIP_UDP_BUF->srcport;
527  uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr);
528  (*packet)->dst.port = UIP_UDP_BUF->destport;
529 
530  if (!is_local_if(&ep->addr, &(*packet)->dst)) {
531  coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
532  goto error;
533  }
534 
535  len = uip_datalen();
536 
537  if (len > coap_get_max_packetlength(*packet)) {
538  /* FIXME: we might want to send back a response */
539  warn("discarded oversized packet\n");
540  return -1;
541  }
542 
543  ((char *)uip_appdata)[len] = 0;
544 #ifndef NDEBUG
545  if (LOG_DEBUG <= coap_get_log_level()) {
546 #ifndef INET6_ADDRSTRLEN
547 #define INET6_ADDRSTRLEN 40
548 #endif
549  unsigned char addr_str[INET6_ADDRSTRLEN+8];
550 
551  if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) {
552  debug("received %zd bytes from %s\n", len, addr_str);
553  }
554  }
555 #endif /* NDEBUG */
556 
557  (*packet)->length = len;
558  memcpy(&(*packet)->payload, uip_appdata, len);
559  }
560 
561 #undef UIP_IP_BUF
562 #undef UIP_UDP_BUF
563 #endif /* WITH_CONTIKI */
564 #ifdef WITH_LWIP
565 #error "coap_network_read() not implemented on this platform"
566 #endif
567 
568  (*packet)->interface = ep;
569 
570  return len;
571  error:
572  coap_free_packet(*packet);
573  *packet = NULL;
574  return -1;
575 }
576 
577 #undef SIN6
578 
579 #endif /* CUSTOM_COAP_NETWORK_READ */
void * conn
opaque connection (e.g.
Definition: coap_io.h:43
ssize_t coap_network_send(struct coap_context_t *context UNUSED_PARAM, const coap_endpoint_t *local_interface, const coap_address_t *dst, unsigned char *data, size_t datalen)
Definition: coap_io.c:236
#define warn(...)
Definition: debug.h:64
coap_address_t addr
local interface address
Definition: coap_io.h:54
struct sockaddr_in6 sin6
Definition: address.h:63
struct sockaddr_in sin
Definition: address.h:62
static void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:70
void coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
Given a packet, set msg and msg_len to an address and length of the packet&#39;s data in memory...
Definition: coap_io.c:392
multi-purpose address abstraction
Definition: address.h:57
void coap_free_endpoint(coap_endpoint_t *ep)
Definition: coap_io.c:195
int ifindex
Definition: coap_io.c:47
coap_endpoint_t * coap_new_endpoint(const coap_address_t *addr, int flags)
Definition: coap_io.c:120
struct in_addr ipi_spec_dst
Definition: coap_io.c:219
struct coap_packet_t coap_packet_t
Definition: coap_io.h:31
static size_t coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM)
Definition: coap_io.c:374
Abstraction of virtual endpoint that can be attached to coap_context_t.
Definition: coap_io.h:39
static int coap_is_mcast(const coap_address_t *a)
Checks if given address a denotes a multicast address.
Definition: address.h:154
static struct coap_endpoint_t * coap_malloc_posix_endpoint(void)
Definition: coap_io.c:110
size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len)
Definition: debug.c:162
#define debug(...)
Definition: debug.h:65
int fd
on POSIX systems
Definition: coap_io.h:42
struct in6_addr ipi6_addr
Definition: coap_io.c:213
void * session
opaque session data
Definition: coap_io.c:48
void coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target)
Populate the coap_endpoint_t *target from the incoming packet&#39;s destination data. ...
Definition: coap_io.c:379
coap_address_t src
the packet&#39;s source address
Definition: coap_io.c:43
coap_if_handle_t hnd
the interface handle
Definition: coap_io.c:42
const coap_endpoint_t * interface
Definition: coap_io.c:45
void coap_free_packet(coap_packet_t *packet)
Releases the storage allocated for packet.
Definition: coap_io.c:357
unsigned char payload[]
payload
Definition: coap_io.c:51
#define assert(...)
Definition: mem.c:17
#define UNUSED_PARAM
Definition: coap_io.c:232
ssize_t coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet)
Function interface for reading data.
Definition: coap_io.c:410
#define COAP_MAX_PDU_SIZE
Definition: pdu.h:27
#define COAP_ENDPOINT_DTLS
Definition: coap_io.h:60
#define SIN6(A)
Definition: coap_io.c:341
static int is_local_if(const coap_address_t *local, const coap_address_t *dst)
Checks if a message with destination address dst matches the local interface with address local...
Definition: coap_io.c:404
static coap_packet_t * coap_malloc_packet(void)
Definition: coap_io.c:345
static int coap_address_isany(const coap_address_t *a)
Checks if given address object a denotes the wildcard address.
Definition: address.h:144
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
Definition: address.c:17
static void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: address.h:116
coap_address_t dst
the packet&#39;s destination address
Definition: coap_io.c:44
size_t length
length of payload
Definition: coap_io.c:50
void coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target)
Given an incoming packet, copy its source address into an address struct.
Definition: coap_io.c:387
static void coap_free_posix_endpoint(struct coap_endpoint_t *ep)
Definition: coap_io.c:115
#define SOL_IP
Definition: coap_io.c:226
static void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:77
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
#define INET6_ADDRSTRLEN
int ipi_ifindex
Definition: coap_io.c:218
union coap_address_t::@0 addr
unsigned int ipi6_ifindex
Definition: coap_io.c:214
socklen_t size
size of addr
Definition: address.h:58
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
#define coap_log(...)
Definition: debug.h:57
union coap_endpoint_t::@1 handle
opaque handle to identify this endpoint
coap_log_t coap_get_log_level(void)
Returns the current log level.
Definition: debug.c:60
int coap_if_handle_t
Abstract handle that is used to identify a local network interface.
Definition: coap_io.h:25
The CoAP stack&#39;s global state is stored in a coap_context_t object.
Definition: net.h:77
struct sockaddr sa
Definition: address.h:60