diff --git a/Makefile.dep b/Makefile.dep index 4afce6fbeb7a1c8b36c7528f62db16208744a082..4378b98f7b70c72375cb3c0f5ca1062a3ddf0c8e 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -373,6 +373,14 @@ ifneq (,$(filter lwip_udplite,$(USEMODULE))) USEMODULE += lwip_udp endif +ifneq (,$(filter lwip_conn_%,$(USEMODULE))) + USEMODULE += lwip_conn +endif + +ifneq (,$(filter lwip_conn_ip,$(USEMODULE))) + USEMODULE += lwip_raw +endif + ifneq (,$(filter lwip_%,$(USEMODULE))) USEMODULE += lwip endif diff --git a/Makefile.pseudomodules b/Makefile.pseudomodules index ee4ad6ec2c598f9e7f72defaac1bb5f7778fa4ce..e75766de79d10b948107b2f3b7a5c04b803910b2 100644 --- a/Makefile.pseudomodules +++ b/Makefile.pseudomodules @@ -18,7 +18,6 @@ PSEUDOMODULES += log PSEUDOMODULES += log_printfnoformat PSEUDOMODULES += lwip_arp PSEUDOMODULES += lwip_autoip -PSEUDOMODULES += lwip_conn PSEUDOMODULES += lwip_dhcp PSEUDOMODULES += lwip_ethernet PSEUDOMODULES += lwip_igmp diff --git a/pkg/lwip/Makefile.include b/pkg/lwip/Makefile.include index a59a21b64fb248a028adf26ba3d39b4c883ce0ba..1bd97c9b1a22455df0db257a897f9384cc391692 100644 --- a/pkg/lwip/Makefile.include +++ b/pkg/lwip/Makefile.include @@ -1,6 +1,12 @@ INCLUDES += -I$(RIOTBASE)/pkg/lwip/include \ -I$(BINDIRBASE)/pkg/$(BOARD)/lwip/src/include +ifneq (,$(filter lwip_conn,$(USEMODULE))) + DIRS += $(RIOTBASE)/pkg/lwip/contrib/conn +endif +ifneq (,$(filter lwip_conn_ip,$(USEMODULE))) + DIRS += $(RIOTBASE)/pkg/lwip/contrib/conn/ip +endif ifneq (,$(filter lwip_contrib,$(USEMODULE))) DIRS += $(RIOTBASE)/pkg/lwip/contrib endif diff --git a/pkg/lwip/contrib/conn/Makefile b/pkg/lwip/contrib/conn/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..e89c126dda3fbb5cc07f8da40457422ff3d8cace --- /dev/null +++ b/pkg/lwip/contrib/conn/Makefile @@ -0,0 +1,3 @@ +MODULE := lwip_conn + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/lwip/contrib/conn/ip/Makefile b/pkg/lwip/contrib/conn/ip/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..0e758e17e1a4af66b34ca670ba1a74f484240938 --- /dev/null +++ b/pkg/lwip/contrib/conn/ip/Makefile @@ -0,0 +1,3 @@ +MODULE := lwip_conn_ip + +include $(RIOTBASE)/Makefile.base diff --git a/pkg/lwip/contrib/conn/ip/lwip_conn_ip.c b/pkg/lwip/contrib/conn/ip/lwip_conn_ip.c new file mode 100644 index 0000000000000000000000000000000000000000..f30d93b1eea252ca08ecc5cc78c8e8df125a86f0 --- /dev/null +++ b/pkg/lwip/contrib/conn/ip/lwip_conn_ip.c @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ + +#include <assert.h> +#include <errno.h> + +#include "net/ipv4/addr.h" +#include "net/ipv6/addr.h" +#include "net/conn/ip.h" + +#include "lwip/api.h" +#include "lwip/conn.h" + +int conn_ip_create(conn_ip_t *conn, const void *addr, size_t addr_len, int family, int proto) +{ + struct netconn *tmp; + int res; + + res = lwip_conn_create(&tmp, addr, addr_len, family, NETCONN_RAW, proto, 0); + if (res < 0) { + return res; + } + conn->lwip_conn = tmp; + + return res; +} + +void conn_ip_close(conn_ip_t *conn) +{ + assert(conn != NULL); + netconn_delete(conn->lwip_conn); +} + +int conn_ip_getlocaladdr(conn_ip_t *conn, void *addr) +{ + assert(conn != NULL); + return lwip_conn_getlocaladdr(conn->lwip_conn, addr, NULL); +} + +int conn_ip_recvfrom(conn_ip_t *conn, void *data, size_t max_len, void *addr, size_t *addr_len) +{ + assert(conn != NULL); + return lwip_conn_recvfrom(conn->lwip_conn, data, max_len, addr, addr_len, NULL); +} + +int conn_ip_sendto(const void *data, size_t len, const void *src, size_t src_len, + void *dst, size_t dst_len, int family, int proto) +{ + struct netconn *tmp; + int res; + + res = lwip_conn_create(&tmp, src, src_len, family, NETCONN_RAW, proto, 0); + if (res < 0) { + return res; + } + res = lwip_conn_sendto(tmp, data, len, dst, dst_len, 0); + netconn_delete(tmp); + return res; +} + +/** @} */ diff --git a/pkg/lwip/contrib/conn/lwip_conn.c b/pkg/lwip/contrib/conn/lwip_conn.c new file mode 100644 index 0000000000000000000000000000000000000000..589a0032cb313151d55eddf5b381731e28049722 --- /dev/null +++ b/pkg/lwip/contrib/conn/lwip_conn.c @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2015 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ + +#include <errno.h> +#include <stdbool.h> + +#include "byteorder.h" +#include "net/af.h" +#include "net/ipv4/addr.h" +#include "net/ipv6/addr.h" +#include "net/conn.h" + +#include "lwip/api.h" +#include "lwip/opt.h" + +int lwip_conn_create(struct netconn **netconn, const void *addr, size_t addr_len, int family, + int type, int proto, uint16_t port) +{ + struct netconn *tmp; + int res = 0; + + switch (family) { +#if LWIP_IPV4 + case AF_INET: + if (addr_len != sizeof(ipv4_addr_t)) { + return -EINVAL; + } + break; +#endif +#if LWIP_IPV6 + case AF_INET6: + if (addr_len != sizeof(ipv6_addr_t)) { + return -EINVAL; + } + type |= NETCONN_TYPE_IPV6; + break; +#endif + default: + return -EAFNOSUPPORT; + } + if ((tmp = netconn_new_with_proto_and_callback(type, proto, NULL)) == NULL) { + return -ENOMEM; + } + switch (netconn_bind(tmp, (ip_addr_t *)addr, port)) { + case ERR_USE: + netconn_delete(tmp); + res = -EADDRINUSE; + break; + case ERR_VAL: + netconn_delete(tmp); + res = -EINVAL; + break; + default: + break; + } + *netconn = tmp; + return res; +} + +int lwip_conn_getlocaladdr(struct netconn *netconn, void *addr, uint16_t *port) +{ + uint16_t tmp; + + if (netconn_getaddr(netconn, addr, &tmp, 1) != ERR_OK) { + return -EOPNOTSUPP; + } + if (port != NULL) { + *port = tmp; + } +#if LWIP_IPV6 + if (netconn->type & NETCONN_TYPE_IPV6) { + return sizeof(ipv6_addr_t); + } +#endif +#if LWIP_IPV4 + return sizeof(ipv4_addr_t); +#else + return -EOPNOTSUPP; +#endif +} + +int lwip_conn_recvfrom(struct netconn *netconn, void *data, size_t max_len, void *addr, + size_t *addr_len, uint16_t *port) +{ + struct netbuf *buf; + size_t len = 0; + err_t res = 0; + uint8_t *data_ptr = data; + + if (netconn == NULL) { + return -ENOTSOCK; + } + if ((res = netconn_recv(netconn, &buf))) { + switch (res) { +#if LWIP_SO_RCVTIMEO + case ERR_TIMEOUT: + return -ETIMEDOUT; +#endif + case ERR_MEM: + return -ENOMEM; + default: + return -EIO; + } + } + len = buf->p->tot_len; + if (len > max_len) { + netbuf_delete(buf); + return -ENOBUFS; + } +#if LWIP_IPV6 + if (netconn->type & NETCONN_TYPE_IPV6) { + *addr_len = sizeof(ipv6_addr_t); + } + else { +#endif +#if LWIP_IPV4 + *addr_len = sizeof(ipv4_addr_t); +#else + netbuf_delete(buf); + return -EOPNOTSUPP; +#endif +#if LWIP_IPV6 + } +#endif + /* copy address */ + memcpy(addr, &buf->addr, *addr_len); + /* copy port */ + if (port != NULL) { + *port = buf->port; + } + /* copy data */ + for (struct pbuf *q = buf->p; q != NULL; q = q->next) { + memcpy(data_ptr, q->payload, q->len); + data_ptr += q->len; + } + + netbuf_delete(buf); + + return (int)len; +} + +int lwip_conn_sendto(struct netconn *netconn, const void *data, size_t len, + const void *addr, size_t addr_len, uint16_t port) +{ + struct netbuf *buf; + int res; + +#if LWIP_IPV6 + if (netconn->type & NETCONN_TYPE_IPV6) { + if (addr_len != sizeof(ipv6_addr_t)) { + return -EINVAL; + } + } + else { +#endif +#if LWIP_IPV4 + if (addr_len != sizeof(ipv4_addr_t)) { + return -EINVAL; + } +#endif +#if LWIP_IPV6 + } +#endif + buf = netbuf_new(); + if ((buf == NULL) || (netbuf_alloc(buf, len) == NULL)) { + netbuf_delete(buf); + return -ENOMEM; + } + if (netbuf_take(buf, data, len) != ERR_OK) { + netbuf_delete(buf); + return -ENOBUFS; + } + switch ((res = netconn_sendto(netconn, buf, addr, port))) { + case ERR_OK: + res = len; + break; + case ERR_RTE: + res = -EHOSTUNREACH; + break; + case ERR_VAL: + res = -EINVAL; + break; + case ERR_IF: + res = -EAFNOSUPPORT; + break; + default: + res = -EIO; + break; + } + netbuf_delete(buf); + return res; +} + +/** @} */ diff --git a/pkg/lwip/include/lwip/conn.h b/pkg/lwip/include/lwip/conn.h new file mode 100644 index 0000000000000000000000000000000000000000..be7bda1cff450ea0f32a33a136606cbef0e0fefc --- /dev/null +++ b/pkg/lwip/include/lwip/conn.h @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2015 Martine Lenders <mlenders@inf.fu-berlin.de> + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup pkg_lwip_conn Connection type definitions for lwIP + * @ingroup pkg_lwip + * @{ + * + * @file + * + * @author Martine Lenders <mlenders@inf.fu-berlin.de> + */ +#ifndef LWIP_CONN_H_ +#define LWIP_CONN_H_ + +#include "lwip/api.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Generic @ref net_conn object for lwIP (used internally) + */ +struct conn { + struct netconn *lwip_conn; /**< stack-internal connection object */ +}; + +/** + * @brief @ref net_conn_ip definition for lwIP + */ +struct conn_ip { + struct netconn *lwip_conn; /**< stack-internal connection object */ +}; + +/** + * @brief @ref net_conn_udp definition for lwIP + */ +struct conn_udp { + struct netconn *lwip_conn; /**< stack-internal connection object */ +}; + +/** + * @brief Internal consolidation functions + * @{ + */ +/** + * @brief consolidation function for @ref conn_ip_create() and @ref + * conn_udp_create() + * + * @internal + */ +int lwip_conn_create(struct netconn **netconn, const void *addr, size_t addr_len, + int family, int type, int proto, uint16_t port); + +/** + * @brief consolidation function for @ref conn_ip_getlocaladdr() and @ref + * conn_udp_getlocaladdr() + * + * @internal + */ +int lwip_conn_getlocaladdr(struct netconn *netconn, void *addr, uint16_t *port); + +/** + * @brief consolidation function for @ref conn_ip_recvfrom() and @ref + * conn_udp_recvfrom() + * + * @internal + */ +int lwip_conn_recvfrom(struct netconn *netconn, void *data, size_t max_len, + void *addr, size_t *addr_len, uint16_t *port); + +/** + * @brief consolidation function for @ref conn_ip_sendto() and @ref + * conn_udp_sendto() + * + * @internal + */ +int lwip_conn_sendto(struct netconn *netconn, const void *data, size_t len, + const void *addr, size_t addr_len, uint16_t port); +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* LWIP_CONN_H_ */ +/** @} */ diff --git a/sys/include/net/conn/ip.h b/sys/include/net/conn/ip.h index ee7cf92081ac0a15573a664f767fa452807ec057..4df3e8626b1ef240ae68bb770ce74c42acf8f957 100644 --- a/sys/include/net/conn/ip.h +++ b/sys/include/net/conn/ip.h @@ -27,6 +27,10 @@ #include "net/gnrc/conn.h" #endif +#ifdef MODULE_LWIP_CONN_IP +#include "lwip/conn.h" +#endif + #ifdef __cplusplus extern "C" { #endif