-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
pkg: provide sock_ip support for lwip
- Loading branch information
Showing
16 changed files
with
2,770 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MODULE := lwip_sock | ||
|
||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
MODULE := lwip_sock_ip | ||
|
||
include $(RIOTBASE)/Makefile.base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
/* | ||
* Copyright (C) 2016 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 <m.lenders@fu-berlin.de> | ||
*/ | ||
|
||
#include <errno.h> | ||
|
||
#include "net/ipv4/addr.h" | ||
#include "net/ipv6/addr.h" | ||
#include "net/ipv6/hdr.h" | ||
#include "net/sock/ip.h" | ||
#include "timex.h" | ||
|
||
#include "lwip/api.h" | ||
#include "lwip/ip4.h" | ||
#include "lwip/ip6.h" | ||
#include "lwip/opt.h" | ||
#include "lwip/sys.h" | ||
#include "lwip/sock_internal.h" | ||
|
||
|
||
int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local, | ||
const sock_ip_ep_t *remote, uint8_t proto, uint16_t flags) | ||
{ | ||
assert(sock != NULL); | ||
|
||
int res; | ||
struct netconn *tmp = NULL; | ||
|
||
/* we pay attention in lwip_sock_create that _sock_tl_ep::port is not | ||
* touched for RAW */ | ||
if ((res = lwip_sock_create(&tmp, (struct _sock_tl_ep *)local, | ||
(struct _sock_tl_ep *)remote, proto, flags, | ||
NETCONN_RAW)) == 0) { | ||
sock->conn = tmp; | ||
} | ||
return res; | ||
} | ||
|
||
void sock_ip_close(sock_ip_t *sock) | ||
{ | ||
assert(sock != NULL); | ||
if (sock->conn != NULL) { | ||
netconn_delete(sock->conn); | ||
sock->conn = NULL; | ||
} | ||
} | ||
|
||
int sock_ip_get_local(sock_ip_t *sock, sock_ip_ep_t *ep) | ||
{ | ||
assert(sock != NULL); | ||
return (lwip_sock_get_addr(sock->conn, (struct _sock_tl_ep *)ep, | ||
1)) ? -EADDRNOTAVAIL : 0; | ||
} | ||
|
||
int sock_ip_get_remote(sock_ip_t *sock, sock_ip_ep_t *ep) | ||
{ | ||
assert(sock != NULL); | ||
return (lwip_sock_get_addr(sock->conn, (struct _sock_tl_ep *)ep, | ||
0)) ? -ENOTCONN : 0; | ||
} | ||
|
||
#if LWIP_IPV4 | ||
static uint16_t _ip4_addr_to_netif(const ip4_addr_p_t *addr) | ||
{ | ||
assert(addr != NULL); | ||
|
||
if (!ip4_addr_isany(addr)) { | ||
for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { | ||
if (netif_ip4_addr(netif)->addr == addr->addr) { | ||
return (int)netif->num + 1; | ||
} | ||
} | ||
} | ||
return SOCK_ADDR_ANY_NETIF; | ||
} | ||
#endif | ||
|
||
#if LWIP_IPV6 | ||
static uint16_t _ip6_addr_to_netif(const ip6_addr_p_t *_addr) | ||
{ | ||
ip6_addr_t addr; | ||
|
||
assert(_addr != NULL); | ||
ip6_addr_copy(addr, *_addr); | ||
if (!ip6_addr_isany_val(addr)) { | ||
for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { | ||
if (netif_get_ip6_addr_match(netif, &addr) >= 0) { | ||
return (int)netif->num + 1; | ||
} | ||
} | ||
} | ||
return SOCK_ADDR_ANY_NETIF; | ||
} | ||
#endif | ||
|
||
static int _parse_iphdr(const struct netbuf *buf, void *data, size_t max_len, | ||
sock_ip_ep_t *remote) | ||
{ | ||
uint8_t *data_ptr = buf->p->payload; | ||
size_t data_len = buf->p->len; | ||
|
||
assert(buf->p->next == NULL); /* TODO this might not be generally the case | ||
* check later with larger payloads */ | ||
switch (data_ptr[0] >> 4) { | ||
#if LWIP_IPV4 | ||
case 4: | ||
if ((data_len - sizeof(struct ip_hdr)) > max_len) { | ||
return -ENOBUFS; | ||
} | ||
if (remote != NULL) { | ||
struct ip_hdr *iphdr = (struct ip_hdr *)data_ptr; | ||
|
||
assert(buf->p->len > sizeof(struct ip_hdr)); | ||
remote->family = AF_INET; | ||
memcpy(&remote->addr, &iphdr->src, sizeof(ip4_addr_t)); | ||
remote->netif = _ip4_addr_to_netif(&iphdr->dest); | ||
} | ||
data_ptr += sizeof(struct ip_hdr); | ||
data_len -= sizeof(struct ip_hdr); | ||
break; | ||
#endif | ||
#if LWIP_IPV6 | ||
case 6: | ||
if ((data_len - sizeof(struct ip6_hdr)) > max_len) { | ||
return -ENOBUFS; | ||
} | ||
if (remote != NULL) { | ||
struct ip6_hdr *iphdr = (struct ip6_hdr *)data_ptr; | ||
|
||
assert(buf->p->len > sizeof(struct ip6_hdr)); | ||
remote->family = AF_INET6; | ||
memcpy(&remote->addr, &iphdr->src, sizeof(ip6_addr_t)); | ||
remote->netif = _ip6_addr_to_netif(&iphdr->dest); | ||
} | ||
data_ptr += sizeof(struct ip6_hdr); | ||
data_len -= sizeof(struct ip6_hdr); | ||
break; | ||
#endif | ||
default: | ||
return -EPROTO; | ||
} | ||
memcpy(data, data_ptr, data_len); | ||
return (ssize_t)data_len; | ||
} | ||
|
||
ssize_t sock_ip_recv(sock_ip_t *sock, void *data, size_t max_len, | ||
uint32_t timeout, sock_ip_ep_t *remote) | ||
{ | ||
struct netbuf *buf; | ||
int res; | ||
|
||
assert((sock != NULL) && (data != NULL) && (max_len > 0)); | ||
if ((res = lwip_sock_recv(sock->conn, timeout, &buf)) < 0) { | ||
return res; | ||
} | ||
res = _parse_iphdr(buf, data, max_len, remote); | ||
netbuf_delete(buf); | ||
return res; | ||
} | ||
|
||
ssize_t sock_ip_send(sock_ip_t *sock, const void *data, size_t len, | ||
uint8_t proto, const sock_ip_ep_t *remote) | ||
{ | ||
assert((sock != NULL) || (remote != NULL)); | ||
assert((len == 0) || (data != NULL)); /* (len != 0) => (data != NULL) */ | ||
return lwip_sock_send(&sock->conn, data, len, proto, | ||
(struct _sock_tl_ep *)remote, NETCONN_RAW); | ||
} | ||
|
||
/** @} */ |
Oops, something went wrong.