From 410f44f07dc3a1af1ee56c8acadc10e593b0e3d3 Mon Sep 17 00:00:00 2001 From: Martine Lenders <mlenders@inf.fu-berlin.de> Date: Fri, 27 Nov 2015 17:14:25 +0100 Subject: [PATCH] lwip: initial import of conn_ip wrapper --- Makefile.dep | 8 + Makefile.pseudomodules | 1 - pkg/lwip/Makefile.include | 6 + pkg/lwip/contrib/conn/Makefile | 3 + pkg/lwip/contrib/conn/ip/Makefile | 3 + pkg/lwip/contrib/conn/ip/lwip_conn_ip.c | 73 +++++++++ pkg/lwip/contrib/conn/lwip_conn.c | 206 ++++++++++++++++++++++++ pkg/lwip/include/lwip/conn.h | 93 +++++++++++ sys/include/net/conn/ip.h | 4 + 9 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 pkg/lwip/contrib/conn/Makefile create mode 100644 pkg/lwip/contrib/conn/ip/Makefile create mode 100644 pkg/lwip/contrib/conn/ip/lwip_conn_ip.c create mode 100644 pkg/lwip/contrib/conn/lwip_conn.c create mode 100644 pkg/lwip/include/lwip/conn.h diff --git a/Makefile.dep b/Makefile.dep index 4afce6fbeb..4378b98f7b 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 ee4ad6ec2c..e75766de79 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 a59a21b64f..1bd97c9b1a 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 0000000000..e89c126dda --- /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 0000000000..0e758e17e1 --- /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 0000000000..f30d93b1ee --- /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 0000000000..589a0032cb --- /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 0000000000..be7bda1cff --- /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 ee7cf92081..4df3e8626b 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 -- GitLab