9 #include "coap_config.h" 15 #ifdef HAVE_SYS_SELECT_H 16 # include <sys/select.h> 18 #ifdef HAVE_SYS_SOCKET_H 19 # include <sys/socket.h> 21 #ifdef HAVE_NETINET_IN_H 22 # include <netinet/in.h> 42 #if defined(IP_PKTINFO) 43 # define GEN_IP_PKTINFO IP_PKTINFO 44 #elif defined(IP_RECVDSTADDR) 45 # define GEN_IP_PKTINFO IP_RECVDSTADDR 47 # error "Need IP_PKTINFO or IP_RECVDSTADDR to request ancillary data from OS." 51 #ifdef IPV6_RECVPKTINFO 52 # define GEN_IPV6_PKTINFO IPV6_RECVPKTINFO 53 #elif defined(IPV6_PKTINFO) 54 # define GEN_IPV6_PKTINFO IPV6_PKTINFO 56 # error "Need IPV6_PKTINFO or IPV6_RECVPKTINFO to request ancillary data from OS." 73 #ifndef CUSTOM_COAP_NETWORK_ENDPOINT 76 static int ep_initialized = 0;
79 coap_malloc_contiki_endpoint() {
110 ep->
addr.port = addr->port;
111 udp_bind((
struct uip_udp_conn *)ep->
handle.
conn, addr->port);
120 uip_udp_remove((
struct uip_udp_conn *)ep->
handle.
conn);
122 coap_free_contiki_endpoint(ep);
139 int sockfd = socket(addr->
addr.
sa.sa_family, SOCK_DGRAM, 0);
148 if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on,
sizeof(on)) < 0)
152 switch(addr->
addr.
sa.sa_family) {
154 if (setsockopt(sockfd, IPPROTO_IP, GEN_IP_PKTINFO, &on,
sizeof(on)) < 0)
158 if (setsockopt(sockfd, IPPROTO_IPV6, GEN_IPV6_PKTINFO, &on,
sizeof(on)) < 0)
165 if (bind(sockfd, &addr->
addr.
sa, addr->
size) < 0) {
191 #ifndef INET6_ADDRSTRLEN 192 #define INET6_ADDRSTRLEN 40 197 debug(
"created %sendpoint %s\n",
219 #ifndef CUSTOM_COAP_NETWORK_SEND 221 #if defined(WITH_POSIX) != defined(HAVE_NETINET_IN_H) 226 struct in6_addr ipi6_addr;
232 struct in_addr ipi_spec_dst;
233 struct in_addr ipi_addr;
237 #if defined(WITH_POSIX) && !defined(SOL_IP) 239 #define SOL_IP IPPROTO_IP 243 #define UNUSED_PARAM __attribute__ ((unused)) 260 char buf[CMSG_LEN(
sizeof(
struct sockaddr_storage))];
266 iov[0].iov_base = data;
267 iov[0].iov_len = datalen;
269 memset(&mhdr, 0,
sizeof(
struct msghdr));
270 mhdr.msg_name = (
void *)&dst->
addr;
271 mhdr.msg_namelen = dst->
size;
276 switch (dst->
addr.
sa.sa_family) {
278 struct cmsghdr *cmsg;
281 mhdr.msg_control = buf;
282 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
284 cmsg = CMSG_FIRSTHDR(&mhdr);
285 cmsg->cmsg_level = IPPROTO_IPV6;
286 cmsg->cmsg_type = IPV6_PKTINFO;
287 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in6_pktinfo));
307 #if defined(IP_PKTINFO) 308 struct cmsghdr *cmsg;
311 mhdr.msg_control = buf;
312 mhdr.msg_controllen = CMSG_SPACE(
sizeof(
struct in_pktinfo));
314 cmsg = CMSG_FIRSTHDR(&mhdr);
315 cmsg->cmsg_level =
SOL_IP;
316 cmsg->cmsg_type = IP_PKTINFO;
317 cmsg->cmsg_len = CMSG_LEN(
sizeof(
struct in_pktinfo));
319 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
320 memset(pktinfo, 0,
sizeof(
struct in_pktinfo));
342 return sendmsg(ep->
handle.
fd, &mhdr, 0);
346 uip_udp_packet_sendto((
struct uip_udp_conn *)ep->
handle.
conn, data, datalen,
347 &dst->
addr, dst->port);
354 #ifndef CUSTOM_COAP_NETWORK_READ 356 #define SIN6(A) ((struct sockaddr_in6 *)(A)) 366 memset(packet, 0, need);
397 memcpy(&target->
addr, &packet->
dst,
sizeof(target->
addr));
429 char msg_control[CMSG_LEN(
sizeof(
struct sockaddr_storage))];
440 warn(
"coap_network_read: insufficient memory, drop packet\n");
448 iov[0].iov_base = (*packet)->payload;
451 memset(&mhdr, 0,
sizeof(
struct msghdr));
453 mhdr.msg_name = &(*packet)->src.addr.st;
454 mhdr.msg_namelen =
sizeof((*packet)->src.addr.st);
459 mhdr.msg_control = msg_control;
460 mhdr.msg_controllen =
sizeof(msg_control);
461 assert(
sizeof(msg_control) == CMSG_LEN(
sizeof(
struct sockaddr_storage)));
463 len = recvmsg(ep->
handle.
fd, &mhdr, 0);
469 struct cmsghdr *cmsg;
474 (*packet)->dst.size =
sizeof((*packet)->dst.addr);
475 if (getsockname(ep->
handle.
fd, &(*packet)->dst.addr.sa, &(*packet)->dst.size) < 0) {
480 (*packet)->length = len;
484 for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
487 if (cmsg->cmsg_level == IPPROTO_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO) {
492 u.c = CMSG_DATA(cmsg);
493 (*packet)->ifindex = (int)(u.p->ipi6_ifindex);
495 memcpy(&(*packet)->dst.addr.sin6.sin6_addr,
496 &u.p->ipi6_addr,
sizeof(
struct in6_addr));
498 (*packet)->src.size =
sizeof(
struct sockaddr_in6);
499 if ((*packet)->src.size != mhdr.msg_namelen) {
504 (*packet)->src.addr.sin6.sin6_family =
SIN6(mhdr.msg_name)->sin6_family;
505 (*packet)->src.addr.sin6.sin6_addr =
SIN6(mhdr.msg_name)->sin6_addr;
506 (*packet)->src.addr.sin6.sin6_port =
SIN6(mhdr.msg_name)->sin6_port;
512 #if defined(IP_PKTINFO) 513 if (cmsg->cmsg_level ==
SOL_IP && cmsg->cmsg_type == IP_PKTINFO) {
519 u.c = CMSG_DATA(cmsg);
520 (*packet)->ifindex = u.p->ipi_ifindex;
522 memcpy(&(*packet)->dst.addr.sin.sin_addr,
523 &u.p->ipi_addr,
sizeof(
struct in_addr));
525 (*packet)->src.size =
sizeof(
struct sockaddr_in);
526 if ((*packet)->src.size != mhdr.msg_namelen) {
531 assert(memcmp(&(*packet)->src.addr.st, mhdr.msg_name, (*packet)->src.size) == 0);
535 #elif defined(IP_RECVDSTADDR) 536 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_RECVDSTADDR) {
537 (*packet)->ifindex = 0;
539 memcpy(&(*packet)->dst.addr.sin.sin_addr,
540 CMSG_DATA(cmsg),
sizeof(
struct in_addr));
542 (*packet)->src.size =
sizeof(
struct sockaddr_in);
543 if ((*packet)->src.size != mhdr.msg_namelen) {
548 assert(memcmp(&(*packet)->src.addr.st, mhdr.msg_name, (*packet)->src.size) == 0);
563 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 564 #define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN]) 567 uip_ipaddr_copy(&(*packet)->src.addr, &UIP_IP_BUF->srcipaddr);
568 (*packet)->src.port = UIP_UDP_BUF->srcport;
569 uip_ipaddr_copy(&(*packet)->dst.addr, &UIP_IP_BUF->destipaddr);
570 (*packet)->dst.port = UIP_UDP_BUF->destport;
581 warn(
"discarded oversized packet\n");
585 ((
char *)uip_appdata)[len] = 0;
588 #ifndef INET6_ADDRSTRLEN 589 #define INET6_ADDRSTRLEN 40 594 debug(
"received %zd bytes from %s\n", len, addr_str);
599 (*packet)->length = len;
600 memcpy(&(*packet)->payload, uip_appdata, len);
607 #error "coap_network_read() not implemented on this platform" 610 (*packet)->interface = ep;
void * conn
opaque connection (e.g.
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)
coap_address_t addr
local interface address
static void * coap_malloc(size_t size)
Wrapper function to coap_malloc_type() for backwards compatibility.
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's data in memory...
multi-purpose address abstraction
void coap_free_endpoint(coap_endpoint_t *ep)
coap_endpoint_t * coap_new_endpoint(const coap_address_t *addr, int flags)
struct in_addr ipi_spec_dst
struct coap_packet_t coap_packet_t
static size_t coap_get_max_packetlength(const coap_packet_t *packet UNUSED_PARAM)
Abstraction of virtual endpoint that can be attached to coap_context_t.
static struct coap_endpoint_t * coap_malloc_posix_endpoint(void)
size_t coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len)
struct in6_addr ipi6_addr
void * session
opaque session data
void coap_packet_populate_endpoint(coap_packet_t *packet, coap_endpoint_t *target)
Populate the coap_endpoint_t *target from the incoming packet's destination data. ...
coap_address_t src
the packet's source address
coap_if_handle_t hnd
the interface handle
const coap_endpoint_t * interface
void coap_free_packet(coap_packet_t *packet)
Releases the storage allocated for packet.
unsigned char payload[]
payload
ssize_t coap_network_read(coap_endpoint_t *ep, coap_packet_t **packet)
Function interface for reading data.
#define COAP_MAX_PDU_SIZE
#define COAP_ENDPOINT_DTLS
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...
static coap_packet_t * coap_malloc_packet(void)
static int coap_address_isany(const coap_address_t *a)
Checks if given address object a denotes the wildcard address.
int coap_address_equals(const coap_address_t *a, const coap_address_t *b)
Compares given address objects a and b.
static void coap_address_init(coap_address_t *addr)
Resets the given coap_address_t object addr to its default values.
coap_address_t dst
the packet's destination address
size_t length
length of payload
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.
static void coap_free_posix_endpoint(struct coap_endpoint_t *ep)
static void coap_free(void *object)
Wrapper function to coap_free_type() for backwards compatibility.
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.
union coap_address_t::@0 addr
unsigned int ipi6_ifindex
socklen_t size
size of addr
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
int coap_is_mcast(const coap_address_t *a)
Checks if given address a denotes a multicast address.
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.
int coap_if_handle_t
Abstract handle that is used to identify a local network interface.
The CoAP stack's global state is stored in a coap_context_t object.