coap_io.c
Go to the documentation of this file.
/* coap_io.h -- Default network I/O functions for libcoap
*
* Copyright (C) 2012,2014 Olaf Bergmann <bergmann@tzi.org>
*
* This file is part of the CoAP library libcoap. Please see
* README for terms of use.
*/
#include "coap_config.h"
#ifdef HAVE_STDIO_H
# include <stdio.h>
#endif
#ifdef HAVE_SYS_SELECT_H
# include <sys/select.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <errno.h>
#ifdef WITH_CONTIKI
# include "uip.h"
#endif
#include "debug.h"
#include "mem.h"
#include "coap_io.h"
#ifdef WITH_POSIX
/* define generic PKTINFO for IPv4 */
#if defined(IP_PKTINFO)
# define GEN_IP_PKTINFO IP_PKTINFO
#elif defined(IP_RECVDSTADDR)
# define GEN_IP_PKTINFO IP_RECVDSTADDR
#else
# error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS."
#endif /* IP_PKTINFO */
/* define generic KTINFO for IPv6 */
#ifdef IPV6_RECVPKTINFO
# define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO
#elif defined(IPV6_PKTINFO)
# define GEN_IPV6_PKTINFO IPV6_PKTINFO
#else
# error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS."
#endif /* IPV6_RECVPKTINFO */
struct coap_packet_t {
coap_if_handle_t hnd;
coap_address_t src;
coap_address_t dst;
const coap_endpoint_t *interface;
int ifindex;
void *session;
size_t length;
unsigned char payload[];
};
#endif
#ifndef CUSTOM_COAP_NETWORK_ENDPOINT
#ifdef WITH_CONTIKI
static int ep_initialized = 0;
static inline struct coap_endpoint_t *
coap_malloc_contiki_endpoint() {
static struct coap_endpoint_t ep;
if (ep_initialized) {
return NULL;
} else {
ep_initialized = 1;
return &ep;
}
}
static inline void
coap_free_contiki_endpoint(struct coap_endpoint_t *ep) {
ep_initialized = 0;
}
coap_endpoint_t *
coap_new_endpoint(const coap_address_t *addr, int flags) {
struct coap_endpoint_t *ep = coap_malloc_contiki_endpoint();
if (ep) {
memset(ep, 0, sizeof(struct coap_endpoint_t));
ep->handle.conn = udp_new(NULL, 0, NULL);
if (!ep->handle.conn) {
coap_free_endpoint(ep);
return NULL;
}
coap_address_init(&ep->addr);
uip_ipaddr_copy(&ep->addr.addr, &addr->addr);
ep->addr.port = addr->port;
udp_bind((struct uip_udp_conn *)ep->handle.conn, addr->port);
}
return ep;
}
void
coap_free_endpoint(coap_endpoint_t *ep) {
if (ep) {
if (ep->handle.conn) {
uip_udp_remove((struct uip_udp_conn *)ep->handle.conn);
}
coap_free_contiki_endpoint(ep);
}
}
#else /* WITH_CONTIKI */
static inline struct coap_endpoint_t *
coap_malloc_posix_endpoint(void) {
return (struct coap_endpoint_t *)coap_malloc(sizeof(struct coap_endpoint_t));
}
static inline void
coap_free_posix_endpoint(struct coap_endpoint_t *ep) {
coap_free(ep);
}
coap_endpoint_t *
coap_new_endpoint(const coap_address_t *addr, int flags) {
int sockfd = socket(addr->addr.sa.sa_family, SOCK_DGRAM, 0);
int on = 1;
struct coap_endpoint_t *ep;
if (sockfd < 0) {
coap_log(LOG_WARNING, "coap_new_endpoint: socket");
return NULL;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
coap_log(LOG_WARNING, "coap_new_endpoint: setsockopt SO_REUSEADDR");
on = 1;
switch(addr->addr.sa.sa_family) {
case AF_INET:
if (setsockopt(sockfd, IPPROTO_IP, GEN_IP_PKTINFO, &on, sizeof(on)) < 0)
coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IP_PKTINFO\n");
break;
case AF_INET6:
if (setsockopt(sockfd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, &on, sizeof(on)) < 0)
coap_log(LOG_ALERT, "coap_new_endpoint: setsockopt IPV6_PKTINFO\n");
break;
default:
coap_log(LOG_ALERT, "coap_new_endpoint: unsupported sa_family\n");
}
if (bind(sockfd, &addr->addr.sa, addr->size) < 0) {
coap_log(LOG_WARNING, "coap_new_endpoint: bind");
close (sockfd);
return NULL;
}
ep = coap_malloc_posix_endpoint();
if (!ep) {
coap_log(LOG_WARNING, "coap_new_endpoint: malloc");
close(sockfd);
return NULL;
}
memset(ep, 0, sizeof(struct coap_endpoint_t));
ep->handle.fd = sockfd;
ep->flags = flags;
ep->addr.size = addr->size;
if (getsockname(sockfd, &ep->addr.addr.sa, &ep->addr.size) < 0) {
coap_log(LOG_WARNING, "coap_new_endpoint: cannot determine local address");
close (sockfd);
return NULL;
}
#ifndef NDEBUG
if (LOG_DEBUG <= coap_get_log_level()) {
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 40
#endif
unsigned char addr_str[INET6_ADDRSTRLEN+8];
if (coap_print_addr(&ep->addr, addr_str, INET6_ADDRSTRLEN+8)) {
debug("created %sendpoint %s\n",
ep->flags & COAP_ENDPOINT_DTLS ? "DTLS " : "",
addr_str);
}
}
#endif /* NDEBUG */
return (coap_endpoint_t *)ep;
}
void
coap_free_endpoint(coap_endpoint_t *ep) {
if(ep) {
if (ep->handle.fd >= 0)
close(ep->handle.fd);
coap_free_posix_endpoint((struct coap_endpoint_t *)ep);
}
}
#endif /* WITH_CONTIKI */
#endif /* CUSTOM_COAP_NETWORK_ENDPOINT */
#ifndef CUSTOM_COAP_NETWORK_SEND
#if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H)
/* define struct in6_pktinfo and struct in_pktinfo if not available
FIXME: check with configure
*/
struct in6_pktinfo {
struct in6_addr ipi6_addr; /* src/dst IPv6 address */
unsigned int ipi6_ifindex; /* send/recv interface index */
};
struct in_pktinfo {
int ipi_ifindex;
struct in_addr ipi_spec_dst;
struct in_addr ipi_addr;
};
#endif
#if defined(WITH_POSIX) && !defined(SOL_IP)
/* Solaris expects level IPPROTO_IP for ancillary data. */
#define SOL_IP IPPROTO_IP
#endif
#ifdef __GNUC__
#define UNUSED_PARAM __attribute__ ((unused))
#else /* not a GCC */
#define UNUSED_PARAM
#endif /* GCC */
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) {
struct coap_endpoint_t *ep =
(struct coap_endpoint_t *)local_interface;
#ifndef WITH_CONTIKI
/* a buffer large enough to hold all protocol address types */
char buf[CMSG_LEN(sizeof(struct sockaddr_storage))];
struct msghdr mhdr;
struct iovec iov[1];
assert(local_interface);
iov[0].iov_base = data;
iov[0].iov_len = datalen;
memset(&mhdr, 0, sizeof(struct msghdr));
mhdr.msg_name = (void *)&dst->addr;
mhdr.msg_namelen = dst->size;
mhdr.msg_iov = iov;
mhdr.msg_iovlen = 1;
switch (dst->addr.sa.sa_family) {
case AF_INET6: {
struct cmsghdr *cmsg;
struct in6_pktinfo *pktinfo;
mhdr.msg_control = buf;
mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo));
cmsg = CMSG_FIRSTHDR(&mhdr);
cmsg->cmsg_level = IPPROTO_IPV6;
cmsg->cmsg_type = IPV6_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
memset(pktinfo, 0, sizeof(struct in6_pktinfo));
pktinfo->ipi6_ifindex = ep->ifindex;
if (coap_is_mcast(&local_interface->addr)) {
/* We cannot send with multicast address as source address
* and hence let the kernel pick the outgoing interface. */
pktinfo->ipi6_ifindex = 0;
memset(&pktinfo->ipi6_addr, 0, sizeof(pktinfo->ipi6_addr));
} else {
pktinfo->ipi6_ifindex = ep->ifindex;
memcpy(&pktinfo->ipi6_addr,
&local_interface->addr.addr.sin6.sin6_addr,
local_interface->addr.size);
}
break;
}
case AF_INET: {
#if defined(IP_PKTINFO)
struct cmsghdr *cmsg;
struct in_pktinfo *pktinfo;
mhdr.msg_control = buf;
mhdr.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
cmsg = CMSG_FIRSTHDR(&mhdr);
cmsg->cmsg_level = SOL_IP;
cmsg->cmsg_type = IP_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
memset(pktinfo, 0, sizeof(struct in_pktinfo));
if (coap_is_mcast(&local_interface->addr)) {
/* We cannot send with multicast address as source address
* and hence let the kernel pick the outgoing interface. */
pktinfo->ipi_ifindex = 0;
memset(&pktinfo->ipi_spec_dst, 0, sizeof(pktinfo->ipi_spec_dst));
} else {
pktinfo->ipi_ifindex = ep->ifindex;
memcpy(&pktinfo->ipi_spec_dst,
&local_interface->addr.addr.sin.sin_addr,
local_interface->addr.size);
}
#endif /* IP_PKTINFO */
break;
}
default:
/* error */
coap_log(LOG_WARNING, "protocol not supported\n");
return -1;
}
return sendmsg(ep->handle.fd, &mhdr, 0);
#else /* WITH_CONTIKI */
/* FIXME: untested */
/* FIXME: is there a way to check if send was successful? */
uip_udp_packet_sendto((struct uip_udp_conn *)ep->handle.conn, data, datalen,
&dst->addr, dst->port);
return datalen;
#endif /* WITH_CONTIKI */
}
#endif /* CUSTOM_COAP_NETWORK_SEND */
#ifndef CUSTOM_COAP_NETWORK_READ
#define SIN6(A) ((struct sockaddr_in6 *)(A))
#ifdef WITH_POSIX
static coap_packet_t *
coap_malloc_packet(void) {
coap_packet_t *packet;
const size_t need = sizeof(coap_packet_t) + COAP_MAX_PDU_SIZE;
packet = (coap_packet_t *)coap_malloc(need);
if (packet) {
memset(packet, 0, need);
}
return packet;
}
void
coap_free_packet(coap_packet_t *packet) {
coap_free(packet);
}
#endif /* WITH_POSIX */
#ifdef WITH_CONTIKI
static inline coap_packet_t *
coap_malloc_packet(void) {
return (coap_packet_t *)coap_malloc_type(COAP_PACKET, 0);
}
void
coap_free_packet(coap_packet_t *packet) {
coap_free_type(COAP_PACKET, packet);
}
#endif /* WITH_CONTIKI */
static inline size_t
coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM) {
return COAP_MAX_PDU_SIZE;
}
void
coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target)
{
target->handle = packet->interface->handle;
memcpy(&target->addr, &packet->dst, sizeof(target->addr));
target->ifindex = packet->ifindex;
target->flags = 0; /* FIXME */
}
void
coap_packet_copy_source(coap_packet_t *packet, coap_address_t *target)
{
memcpy(target, &packet->src, sizeof(coap_address_t));
}
void
coap_packet_get_memmapped(coap_packet_t *packet, unsigned char **address, size_t *length)
{
*address = packet->payload;
*length = packet->length;
}
static inline int
is_local_if(const coap_address_t *local, const coap_address_t *dst) {
return coap_address_isany(local) || coap_address_equals(dst, local) ||
coap_is_mcast(dst);
}
ssize_t
coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet) {
ssize_t len = -1;
#ifdef WITH_POSIX
char msg_control[CMSG_LEN(sizeof(struct sockaddr_storage))];
struct msghdr mhdr;
struct iovec iov[1];
#endif /* WITH_POSIX */
assert(ep);
assert(packet);
*packet = coap_malloc_packet();
if (!*packet) {
warn("coap_network_read: insufficient memory, drop packet\n");
return -1;
}
coap_address_init(&(*packet)->dst); /* the local interface address */
coap_address_init(&(*packet)->src); /* the remote peer */
#ifdef WITH_POSIX
iov[0].iov_base = (*packet)->payload;
iov[0].iov_len = coap_get_max_packetlength(*packet);
memset(&mhdr, 0, sizeof(struct msghdr));
mhdr.msg_name = &(*packet)->src.addr.st;
mhdr.msg_namelen = sizeof((*packet)->src.addr.st);
mhdr.msg_iov = iov;
mhdr.msg_iovlen = 1;
mhdr.msg_control = msg_control;
mhdr.msg_controllen = sizeof(msg_control);
assert(sizeof(msg_control) == CMSG_LEN(sizeof(struct sockaddr_storage)));
len = recvmsg(ep->handle.fd, &mhdr, 0);
if (len < 0) {
coap_log(LOG_WARNING, "coap_network_read: %s\n", strerror(errno));
goto error;
} else {
struct cmsghdr *cmsg;
coap_log(LOG_DEBUG, "received %d bytes on fd %d\n", (int)len, ep->handle.fd);
/* use getsockname() to get the local port */
(*packet)->dst.size = sizeof((*packet)->dst.addr);
if (getsockname(ep->handle.fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) {
coap_log(LOG_DEBUG, "cannot determine local port\n");
goto error;
}
(*packet)->length = len;
/* Walk through ancillary data records until the local interface
* is found where the data was received. */
for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
/* get the local interface for IPv6 */
if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
union {
unsigned char *c;
struct in6_pktinfo *p;
} u;
u.c = CMSG_DATA(cmsg);
(*packet)->ifindex = (int)(u.p->ipi6_ifindex);
memcpy(&(*packet)->dst.addr.sin6.sin6_addr,
&u.p->ipi6_addr, sizeof(struct in6_addr));
(*packet)->src.size = sizeof(struct sockaddr_in6);
if ((*packet)->src.size != mhdr.msg_namelen) {
coap_log(LOG_DEBUG, "wrong IPv6 address length detected, dropped packet\n");
goto error;
}
(*packet)->src.addr.sin6.sin6_family = SIN6(mhdr.msg_name)->sin6_family;
(*packet)->src.addr.sin6.sin6_addr = SIN6(mhdr.msg_name)->sin6_addr;
(*packet)->src.addr.sin6.sin6_port = SIN6(mhdr.msg_name)->sin6_port;
break;
}
/* local interface for IPv4 */
#if defined(IP_PKTINFO)
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
union {
unsigned char *c;
struct in_pktinfo *p;
} u;
u.c = CMSG_DATA(cmsg);
(*packet)->ifindex = u.p->ipi_ifindex;
memcpy(&(*packet)->dst.addr.sin.sin_addr,
&u.p->ipi_addr, sizeof(struct in_addr));
(*packet)->src.size = sizeof(struct sockaddr_in);
if ((*packet)->src.size != mhdr.msg_namelen) {
coap_log(LOG_DEBUG, "wrong IPv4 address length detected, dropped packet\n");
goto error;
}
assert(memcmp(&(*packet)->src.addr.st, mhdr.msg_name, (*packet)->src.size) == 0);
break;
}
#elif defined(IP_RECVDSTADDR)
if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
(*packet)->ifindex = 0;
memcpy(&(*packet)->dst.addr.sin.sin_addr,
CMSG_DATA(cmsg), sizeof(struct in_addr));
(*packet)->src.size = sizeof(struct sockaddr_in);
if ((*packet)->src.size != mhdr.msg_namelen) {
coap_log(LOG_DEBUG, "wrong IPv4 address length detected, dropped packet\n");
goto error;
}
assert(memcmp(&(*packet)->src.addr.st, mhdr.msg_name, (*packet)->src.size) == 0);
break;
}
#endif /* IP_PKTINFO */
}
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
goto error;
}
}
#endif /* WITH_POSIX */
#ifdef WITH_CONTIKI
/* FIXME: untested, make this work */
#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
if(uip_newdata()) {
uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr);
(*packet)->src.port = UIP_UDP_BUF->srcport;
uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr);
(*packet)->dst.port = UIP_UDP_BUF->destport;
if (!is_local_if(&ep->addr, &(*packet)->dst)) {
coap_log(LOG_DEBUG, "packet received on wrong interface, dropped\n");
goto error;
}
len = uip_datalen();
if (len > coap_get_max_packetlength(*packet)) {
/* FIXME: we might want to send back a response */
warn("discarded oversized packet\n");
return -1;
}
((char *)uip_appdata)[len] = 0;
#ifndef NDEBUG
if (LOG_DEBUG <= coap_get_log_level()) {
#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 40
#endif
unsigned char addr_str[INET6_ADDRSTRLEN+8];
if (coap_print_addr(&(*packet)->src, addr_str, INET6_ADDRSTRLEN+8)) {
debug("received %zd bytes from %s\n", len, addr_str);
}
}
#endif /* NDEBUG */
(*packet)->length = len;
memcpy(&(*packet)->payload, uip_appdata, len);
}
#undef UIP_IP_BUF
#undef UIP_UDP_BUF
#endif /* WITH_CONTIKI */
#ifdef WITH_LWIP
#error "coap_network_read() not implemented on this platform"
#endif
(*packet)->interface = ep;
return len;
error:
coap_free_packet(*packet);
*packet = NULL;
return -1;
}
#undef SIN6
#endif /* CUSTOM_COAP_NETWORK_READ */
coap_endpoint_t::conn
void * conn
opaque connection (e.g.
Definition: coap_io.h:39
in_pktinfo
Definition: coap_io.c:230
LOG_WARNING
Definition: debug.h:31
coap_network_send
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:249
warn
#define warn(...)
Definition: debug.h:65
mem.h
coap_endpoint_t::addr
coap_address_t addr
local interface address
Definition: coap_io.h:50
coap_address_t::sin6
struct sockaddr_in6 sin6
Definition: address.h:65
coap_address_t::sin
struct sockaddr_in sin
Definition: address.h:64
LOG_ALERT
Definition: debug.h:28
coap_malloc
static void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
Definition: mem.h:70
coap_packet_get_memmapped
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:407
debug.h
coap_address_t
multi-purpose address abstraction
Definition: address.h:59
coap_free_endpoint
void coap_free_endpoint(coap_endpoint_t *ep)
Definition: coap_io.c:208
coap_packet_t::ifindex
int ifindex
Definition: coap_io.c:65
coap_new_endpoint
coap_endpoint_t * coap_new_endpoint(const coap_address_t *addr, int flags)
Definition: coap_io.c:138
in_pktinfo::ipi_spec_dst
struct in_addr ipi_spec_dst
Definition: coap_io.c:232
coap_packet_t
struct coap_packet_t coap_packet_t
Definition: coap_io.h:27
coap_packet_t
Definition: coap_io.c:59
coap_get_max_packetlength
static size_t coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM)
Definition: coap_io.c:389
LOG_DEBUG
Definition: debug.h:34
coap_endpoint_t
Abstraction of virtual endpoint that can be attached to coap_context_t.
Definition: coap_io.h:35
coap_malloc_posix_endpoint
static struct coap_endpoint_t * coap_malloc_posix_endpoint(void)
Definition: coap_io.c:128
coap_print_addr
size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len)
Definition: debug.c:162
debug
#define debug(...)
Definition: debug.h:66
coap_endpoint_t::fd
int fd
on POSIX systems
Definition: coap_io.h:38
in6_pktinfo::ipi6_addr
struct in6_addr ipi6_addr
Definition: coap_io.c:226
coap_packet_t::session
void * session
opaque session data
Definition: coap_io.c:66
coap_packet_populate_endpoint
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:394
coap_packet_t::src
coap_address_t src
the packet&#39;s source address
Definition: coap_io.c:61
coap_packet_t::hnd
coap_if_handle_t hnd
the interface handle
Definition: coap_io.c:60
coap_packet_t::interface
const coap_endpoint_t * interface
Definition: coap_io.c:63
coap_free_packet
void coap_free_packet(coap_packet_t *packet)
Releases the storage allocated for packet.
Definition: coap_io.c:372
coap_packet_t::payload
unsigned char payload[]
payload
Definition: coap_io.c:69
assert
#define assert(...)
Definition: mem.c:17
in6_pktinfo
Definition: coap_io.c:225
UNUSED_PARAM
#define UNUSED_PARAM
Definition: coap_io.c:245
COAP_PACKET
Definition: mem.h:33
coap_network_read
ssize_t coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet)
Function interface for reading data.
Definition: coap_io.c:425
COAP_MAX_PDU_SIZE
#define COAP_MAX_PDU_SIZE
Definition: pdu.h:27
COAP_ENDPOINT_DTLS
#define COAP_ENDPOINT_DTLS
Definition: coap_io.h:56
SIN6
#define SIN6(A)
Definition: coap_io.c:356
is_local_if
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:419
coap_malloc_packet
static coap_packet_t * coap_malloc_packet(void)
Definition: coap_io.c:360
coap_address_isany
static int coap_address_isany(const coap_address_t *a)
Checks if given address object a denotes the wildcard address.
Definition: address.h:130
coap_address_equals
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
Definition: address.c:18
coap_address_init
static void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
Definition: address.h:102
coap_packet_t::dst
coap_address_t dst
the packet&#39;s destination address
Definition: coap_io.c:62
coap_io.h
coap_packet_t::length
size_t length
length of payload
Definition: coap_io.c:68
coap_packet_copy_source
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:402
coap_free_posix_endpoint
static void coap_free_posix_endpoint(struct coap_endpoint_t *ep)
Definition: coap_io.c:133
SOL_IP
#define SOL_IP
Definition: coap_io.c:239
coap_free
static void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
Definition: mem.h:77
coap_malloc_type
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.
INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN
in_pktinfo::ipi_ifindex
int ipi_ifindex
Definition: coap_io.c:231
coap_address_t::addr
union coap_address_t::@0 addr
in6_pktinfo::ipi6_ifindex
unsigned int ipi6_ifindex
Definition: coap_io.c:227
coap_address_t::size
socklen_t size
size of addr
Definition: address.h:60
coap_free_type
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
coap_log
#define coap_log(...)
Definition: debug.h:58
coap_is_mcast
int coap_is_mcast(const coap_address_t *a)
Checks if given address a denotes a multicast address.
Definition: address.c:41
coap_endpoint_t::ifindex
int ifindex
Definition: coap_io.h:51
coap_endpoint_t::handle
union coap_endpoint_t::@1 handle
opaque handle to identify this endpoint
coap_get_log_level
coap_log_t coap_get_log_level(void)
Returns the current log level.
Definition: debug.c:60
coap_if_handle_t
int coap_if_handle_t
Abstract handle that is used to identify a local network interface.
Definition: coap_io.h:21
coap_context_t
The CoAP stack&#39;s global state is stored in a coap_context_t object.
Definition: net.h:76
coap_address_t::sa
struct sockaddr sa
Definition: address.h:62
coap_endpoint_t::flags
int flags
Definition: coap_io.h:52