2016-06-04 12:18:13 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2016 Alexander Aring <aar@pengutronix.de>
|
|
|
|
* Freie Universität Berlin
|
|
|
|
* HAW Hamburg
|
|
|
|
* Kaspar Schleiser <kaspar@schleiser.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 net_sock_ip Raw IPv4/IPv6 sock API
|
|
|
|
* @ingroup net_sock
|
2016-09-28 15:13:52 +02:00
|
|
|
* @brief Sock submodule for raw IPv4/IPv6
|
|
|
|
*
|
|
|
|
* How To Use
|
|
|
|
* ----------
|
|
|
|
* First you need to @ref including-modules "include" a module that implements
|
|
|
|
* this API in your application's Makefile. For example the implementation for
|
|
|
|
* @ref net_gnrc "GNRC" is called `gnrc_sock_ip`.
|
|
|
|
*
|
|
|
|
* ### A Simple IPv6 Server
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* #include <stdio.h>
|
|
|
|
*
|
|
|
|
* #include "net/protnum.h"
|
|
|
|
* #include "net/sock/ip.h"
|
|
|
|
*
|
|
|
|
* uint8_t buf[128];
|
|
|
|
*
|
|
|
|
* int main(void)
|
|
|
|
* {
|
|
|
|
* sock_ip_ep_t local = SOCK_IPV6_EP_ANY;
|
|
|
|
* sock_ip_t sock;
|
|
|
|
*
|
|
|
|
* if (sock_ip_create(&sock, &local, NULL, PROTNUM_IPV6_NONXT, 0) < 0) {
|
|
|
|
* puts("Error creating raw IP sock");
|
|
|
|
* return 1;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* while (1) {
|
|
|
|
* sock_ip_ep_t remote;
|
|
|
|
* ssize_t res;
|
|
|
|
*
|
2016-10-11 23:23:20 +02:00
|
|
|
* if ((res = sock_ip_recv(&sock, buf, sizeof(buf), SOCK_NO_TIMEOUT,
|
|
|
|
* &remote)) >= 0) {
|
2016-09-28 15:13:52 +02:00
|
|
|
* puts("Received a message");
|
|
|
|
* if (sock_ip_send(&sock, buf, res, 0, &remote) < 0) {
|
|
|
|
* puts("Error sending reply");
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* return 0;
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* Above you see a simple IPv6 server. Don't forget to also
|
|
|
|
* @ref including-modules "include" the IPv6 module of your networking
|
2016-10-11 10:24:45 +02:00
|
|
|
* implementation (e.g. `gnrc_ipv6_default` for @ref net_gnrc "GNRC") and at
|
|
|
|
* least one network device.
|
2016-09-28 15:13:52 +02:00
|
|
|
*
|
|
|
|
* After including header files for the @ref net_af "address families",
|
|
|
|
* @ref net_protnum "protocol numbers" and the @ref net_sock_ip "raw `sock`s"
|
|
|
|
* themselves, we create some buffer space `buf` to store the data received by
|
|
|
|
* the server:
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* #include "net/af.h"
|
|
|
|
* #include "net/protnum.h"
|
|
|
|
* #include "net/sock/ip.h"
|
|
|
|
*
|
|
|
|
* uint8_t buf[128];
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* To be able to listen for incoming packets we bind the `sock` by setting a
|
|
|
|
* local end point (even if we just state here, that we just want to bind it to
|
|
|
|
* any IPv6 address).
|
|
|
|
*
|
|
|
|
* We then proceed to create the `sock`. It is bound to `local` and listens for
|
|
|
|
* IPv6 packets with @ref ipv6_hdr_t::nh "next header field"
|
|
|
|
* @ref PROTNUM_IPV6_NONXT. Since we don't need any further configuration we set
|
|
|
|
* the flags to 0. In case of an error we stop the program:
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* sock_ip_ep_t local = SOCK_IPV6_EP_ANY;
|
|
|
|
* sock_ip_t sock;
|
|
|
|
*
|
|
|
|
* if (sock_ip_create(&sock, &local, NULL, PROTNUM_IPV6_NONXT, 0) < 0) {
|
|
|
|
* puts("Error creating raw IP sock");
|
|
|
|
* return 1;
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* The application then waits indefinitely for an incoming message in
|
|
|
|
* `buf` from `remote`. If we want to timeout this wait period we could
|
|
|
|
* alternatively set the `timeout` parameter of @ref sock_ip_recv() to a
|
2016-10-11 23:23:20 +02:00
|
|
|
* value `!= SOCK_NO_TIMEOUT`. If an error occurs on receive we just ignore it
|
|
|
|
* and continue looping.
|
2016-09-28 15:13:52 +02:00
|
|
|
*
|
|
|
|
* If we receive a message we use its `remote` to reply. Note since the `proto`
|
|
|
|
* was already set during @ref sock_ip_create() we can just leave `proto` for
|
|
|
|
* the @ref sock_ip_send() set to 0 (it is ignored by that function in that case
|
|
|
|
* anyway). In case of an error on send we print an according message:
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* while (1) {
|
|
|
|
* sock_ip_ep_t remote;
|
|
|
|
* ssize_t res;
|
|
|
|
*
|
2016-10-11 23:23:20 +02:00
|
|
|
* if ((res = sock_ip_recv(&sock, buf, sizeof(buf), SOCK_NO_TIMEOUT,
|
|
|
|
* &remote)) >= 0) {
|
2016-09-28 15:13:52 +02:00
|
|
|
* puts("Received a message");
|
|
|
|
* if (sock_ip_send(&sock, buf, res, 0, &remote) < 0) {
|
|
|
|
* puts("Error sending reply");
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* ### A Simple IPv6 Client
|
|
|
|
* There are two kinds of clients. Those that do expect a reply and those who
|
|
|
|
* don't. A client that does not require a reply is very simple to implement in
|
|
|
|
* one line:
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* res = sock_ip_send(NULL, data, data_len, PROTNUM, &remote);
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* With `data` being the data sent, `data_len` the length of `data`, `PROTNUM`
|
|
|
|
* the next header number for the sent packet and `remote` the remote end point
|
|
|
|
* the packet that is to be sent.
|
|
|
|
*
|
|
|
|
* To see some other capabilities we look at a more complex example in form of
|
|
|
|
* the counter of the echo server above:
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* #include <stdio.h>
|
|
|
|
*
|
|
|
|
* #include "net/af.h"
|
|
|
|
* #include "net/protnum.h"
|
|
|
|
* #include "net/ipv6/addr.h"
|
|
|
|
* #include "net/sock/ip.h"
|
|
|
|
* #include "xtimer.h"
|
|
|
|
*
|
|
|
|
* uint8_t buf[7];
|
|
|
|
*
|
|
|
|
* int main(void)
|
|
|
|
* {
|
|
|
|
* sock_ip_ep_t local = SOCK_IPV6_EP_ANY;
|
|
|
|
* sock_ip_t sock;
|
|
|
|
*
|
|
|
|
* if (sock_ip_create(&sock, &local, NULL, PROTNUM_IPV6_NONXT, 0) < 0) {
|
|
|
|
* puts("Error creating raw IP sock");
|
|
|
|
* return 1;
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* while (1) {
|
|
|
|
* sock_ip_ep_t remote = { .family = AF_INET6 };
|
|
|
|
* ssize_t res;
|
|
|
|
*
|
|
|
|
* ipv6_addr_set_all_nodes_multicast((ipv6_addr_t *)&remote.addr.ipv6,
|
|
|
|
* IPV6_ADDR_MCAST_SCP_LINK_LOCAL);
|
|
|
|
*
|
|
|
|
* if (sock_ip_send(&sock, "Hello!", sizeof("Hello!"), 0, &remote) < 0) {
|
|
|
|
* puts("Error sending message");
|
|
|
|
* sock_ip_close(&sock);
|
|
|
|
* return 1;
|
|
|
|
* }
|
2017-01-17 16:44:05 +01:00
|
|
|
* if ((res = sock_ip_recv(&sock, buf, sizeof(buf), 1 * US_PER_SEC,
|
2016-09-28 15:13:52 +02:00
|
|
|
* NULL)) < 0) {
|
|
|
|
* if (res == -ETIMEDOUT) {
|
|
|
|
* puts("Timed out");
|
|
|
|
* }
|
|
|
|
* else {
|
|
|
|
* puts("Error receiving message");
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* else {
|
|
|
|
* printf("Received message: \"");
|
|
|
|
* for (int i = 0; i < res; i++) {
|
|
|
|
* printf("%c", buf[i]);
|
|
|
|
* }
|
|
|
|
* printf("\"\n");
|
|
|
|
* }
|
|
|
|
* xtimer_sleep(1);
|
|
|
|
* }
|
|
|
|
*
|
|
|
|
* return 0;
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* Again: Don't forget to also @ref including-modules "include" the IPv6 module
|
|
|
|
* of your networking implementation (e.g. `gnrc_ipv6_default` for
|
2016-10-11 10:24:45 +02:00
|
|
|
* @ref net_gnrc "GNRC") and at least one network device.
|
2016-09-28 15:13:52 +02:00
|
|
|
*
|
|
|
|
* We first create again a `sock` with a local end point bound to any IPv6
|
|
|
|
* address. Note that we also could specify the remote end point here and not
|
|
|
|
* use it with @ref sock_ip_send().
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* sock_ip_ep_t local = SOCK_IPV6_EP_ANY;
|
|
|
|
* sock_ip_t sock;
|
|
|
|
*
|
|
|
|
* if (sock_ip_create(&sock, &local, NULL, PROTNUM_IPV6_NONXT, 0) < 0) {
|
|
|
|
* puts("Error creating raw IP sock");
|
|
|
|
* return 1;
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* We then create a remote end point for the [link-local all nodes multicast
|
|
|
|
* address](https://tools.ietf.org/html/rfc4291#page-16) (`ff02::1`) and send
|
|
|
|
* a "Hello!" message to that end point.
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
|
|
|
* sock_ip_ep_t remote = { .family = AF_INET6 };
|
|
|
|
* ssize_t res;
|
|
|
|
*
|
|
|
|
* ipv6_addr_set_all_nodes_multicast((ipv6_addr_t *)&remote.addr.ipv6,
|
|
|
|
* IPV6_ADDR_MCAST_SCP_LINK_LOCAL);
|
|
|
|
*
|
|
|
|
* if (sock_ip_send(&sock, "Hello!", sizeof("Hello!"), 0, &remote) < 0) {
|
|
|
|
* puts("Error sending message");
|
|
|
|
* sock_ip_close(&sock);
|
|
|
|
* return 1;
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* We then wait a second for a reply and print it when it is received.
|
|
|
|
*
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ {.c}
|
2017-01-17 16:44:05 +01:00
|
|
|
* if ((res = sock_ip_recv(&sock, buf, sizeof(buf), 1 * US_PER_SEC,
|
2016-09-28 15:13:52 +02:00
|
|
|
* NULL)) < 0) {
|
|
|
|
* if (res == -ETIMEDOUT) {
|
|
|
|
* puts("Timed out");
|
|
|
|
* }
|
|
|
|
* else {
|
|
|
|
* puts("Error receiving message");
|
|
|
|
* }
|
|
|
|
* }
|
|
|
|
* else {
|
|
|
|
* printf("Received message: \"");
|
|
|
|
* for (int i = 0; i < res; i++) {
|
|
|
|
* printf("%c", buf[i]);
|
|
|
|
* }
|
|
|
|
* printf("\"\n");
|
|
|
|
* }
|
|
|
|
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
*
|
|
|
|
* Finally, we wait a second before sending out the next "Hello!" with
|
|
|
|
* `xtimer_sleep(1)`.
|
|
|
|
*
|
2016-06-04 12:18:13 +02:00
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Raw IPv4/IPv6 sock definitions
|
|
|
|
*
|
|
|
|
* @author Alexander Aring <aar@pengutronix.de>
|
|
|
|
* @author Simon Brummer <simon.brummer@haw-hamburg.de>
|
|
|
|
* @author Cenk Gündoğan <mail@cgundogan.de>
|
|
|
|
* @author Peter Kietzmann <peter.kietzmann@haw-hamburg.de>
|
|
|
|
* @author Martine Lenders <m.lenders@fu-berlin.de>
|
|
|
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
|
|
|
*/
|
2017-01-18 13:00:05 +01:00
|
|
|
#ifndef NET_SOCK_IP_H
|
|
|
|
#define NET_SOCK_IP_H
|
2016-06-04 12:18:13 +02:00
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdlib.h>
|
2016-08-19 16:17:35 +02:00
|
|
|
#include <sys/types.h>
|
2016-06-04 12:18:13 +02:00
|
|
|
|
2020-01-06 15:31:41 +01:00
|
|
|
/* net/sock/async/types.h included by net/sock.h needs to re-typedef the
|
|
|
|
* `sock_ip_t` to prevent cyclic includes */
|
|
|
|
#if defined (__clang__)
|
|
|
|
# pragma clang diagnostic push
|
|
|
|
# pragma clang diagnostic ignored "-Wtypedef-redefinition"
|
|
|
|
#endif
|
|
|
|
|
2016-08-19 17:36:58 +02:00
|
|
|
#include "net/sock.h"
|
2016-06-04 12:18:13 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**
|
2016-09-28 15:13:52 +02:00
|
|
|
* @brief Type for a raw IPv4/IPv6 sock object
|
2016-06-04 12:18:13 +02:00
|
|
|
*
|
2016-09-28 15:13:52 +02:00
|
|
|
* @note API implementors: `struct sock_ip` needs to be defined by
|
|
|
|
* implementation-specific `sock_types.h`.
|
2016-06-04 12:18:13 +02:00
|
|
|
*/
|
|
|
|
typedef struct sock_ip sock_ip_t;
|
|
|
|
|
2020-01-06 15:31:41 +01:00
|
|
|
#if defined (__clang__)
|
|
|
|
# pragma clang diagnostic pop
|
|
|
|
#endif
|
|
|
|
|
2020-07-27 10:57:11 +02:00
|
|
|
/**
|
|
|
|
* @brief Auxiliary data provided when receiving using an IP sock object
|
|
|
|
*/
|
|
|
|
typedef struct {
|
|
|
|
#if defined(MODULE_SOCK_AUX_LOCAL) || defined(DOXYGEN)
|
|
|
|
/**
|
|
|
|
* @brief The local address the packet was received on
|
|
|
|
*
|
|
|
|
* @see SOCK_AUX_GET_LOCAL
|
|
|
|
*/
|
|
|
|
sock_ip_ep_t local;
|
|
|
|
#endif /* MODULE_SOCK_AUX_ENDPOINT */
|
|
|
|
#if defined(MODULE_SOCK_AUX_TIMESTAMP) || defined(DOXYGEN)
|
|
|
|
/**
|
|
|
|
* @brief System time the packet was received
|
|
|
|
*
|
|
|
|
* @see SOCK_AUX_GET_TIMESTAMP
|
|
|
|
*/
|
|
|
|
uint64_t timestamp;
|
2021-01-12 21:58:27 +01:00
|
|
|
#endif /* MODULE_SOCK_AUX_TIMESTAP */
|
|
|
|
#if defined(MODULE_SOCK_AUX_RSSI) || defined(DOXYGEN)
|
|
|
|
/**
|
|
|
|
* @brief RSSI value of the received frame
|
|
|
|
*
|
|
|
|
* @see SOCK_AUX_GET_RSSI
|
|
|
|
*/
|
|
|
|
int16_t rssi;
|
|
|
|
#endif /* MODULE_SOCK_AUX_RSSI */
|
2020-07-27 10:57:11 +02:00
|
|
|
sock_aux_flags_t flags; /**< Flags used request information */
|
|
|
|
} sock_ip_aux_rx_t;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Auxiliary data provided when sending using an IP sock object
|
|
|
|
*/
|
|
|
|
typedef struct {
|
|
|
|
#if defined(MODULE_SOCK_AUX_TIMESTAMP) || defined(DOXYGEN)
|
|
|
|
/**
|
|
|
|
* @brief System time the packet was send
|
|
|
|
*
|
|
|
|
* Add @ref SOCK_AUX_GET_TIMESTAMP to the bitmask in
|
|
|
|
* @ref sock_ip_aux_tx_t::flags to request a transmission timestamp. This
|
|
|
|
* bit will be cleared by @ref sock_ip_send_aux if and only if the timestamp
|
|
|
|
* was provided. The module `sock_aux_timestamp` needs to be selected to use
|
|
|
|
* this. The timestamp refers to the transmission of start of frame
|
|
|
|
* delimiter or preamble of the frame carrying the IP packet and is given in
|
|
|
|
* nanoseconds since epoch, unless otherwise documented by the underlying
|
|
|
|
* implementation.
|
|
|
|
*/
|
|
|
|
uint64_t timestamp;
|
|
|
|
#endif /* MODULE_SOCK_AUX_TIMESTAP*/
|
|
|
|
sock_aux_flags_t flags; /**< Flags used request information */
|
|
|
|
} sock_ip_aux_tx_t;
|
|
|
|
|
2016-06-04 12:18:13 +02:00
|
|
|
/**
|
|
|
|
* @brief Creates a new raw IPv4/IPv6 sock object
|
|
|
|
*
|
|
|
|
* @pre `(sock != NULL)`
|
|
|
|
*
|
2016-08-20 02:39:51 +02:00
|
|
|
* @param[out] sock The resulting sock object.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @param[in] local Local end point for the sock object.
|
2016-09-28 15:13:52 +02:00
|
|
|
* May be NULL. sock_ip_ep_t::netif must either be
|
2016-06-04 12:18:13 +02:00
|
|
|
* @ref SOCK_ADDR_ANY_NETIF or equal to sock_ip_ep_t::netif
|
|
|
|
* of @p remote if `remote != NULL`.
|
2016-09-28 15:13:52 +02:00
|
|
|
* If NULL @ref sock_ip_send() may bind implicitly.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @param[in] remote Remote end point for the sock object.
|
|
|
|
* May be `NULL` but then the `remote` parameter of
|
|
|
|
* @ref sock_ip_send() may not be `NULL` or it will always
|
|
|
|
* error with return value -ENOTCONN.
|
|
|
|
* sock_ip_ep_t::port may not be 0 if `remote != NULL`.
|
|
|
|
* sock_ip_ep_t::netif must either be
|
|
|
|
* @ref SOCK_ADDR_ANY_NETIF or equal to sock_ip_ep_t::netif
|
|
|
|
* of @p local if `local != NULL`.
|
|
|
|
* @param[in] proto Protocol to use in the raw IPv4/IPv6 sock object
|
|
|
|
* (the `protocol` header field in IPv4 and the `next_header`
|
|
|
|
* field in IPv6).
|
2016-09-28 15:13:52 +02:00
|
|
|
* @param[in] flags Flags for the sock object. See also
|
|
|
|
* [sock flags](net_sock_flags). May be 0.
|
2016-06-04 12:18:13 +02:00
|
|
|
*
|
|
|
|
* @return 0 on success.
|
2016-09-28 15:13:52 +02:00
|
|
|
* @return -EADDRINUSE, if `local != NULL` and @p local is already used
|
|
|
|
* elsewhere
|
2016-06-04 12:18:13 +02:00
|
|
|
* @return -EAFNOSUPPORT, if `local != NULL` or `remote != NULL` and
|
|
|
|
* sock_ip_ep_t::family of @p local or @p remote is not supported.
|
2016-10-05 17:14:39 +02:00
|
|
|
* @return -EINVAL, if sock_ip_ep_t::addr of @p remote is an invalid address.
|
|
|
|
* @return -EINVAL, if sock_ip_ep_t::netif of @p local or @p remote are not
|
|
|
|
* valid interfaces or contradict each other
|
|
|
|
* (i.e. `(local->netif != remote->netif) &&
|
2016-06-04 12:18:13 +02:00
|
|
|
* ((local->netif != SOCK_ADDR_ANY_NETIF) ||
|
|
|
|
* (remote->netif != SOCK_ADDR_ANY_NETIF))` if neither is `NULL`).
|
2016-09-28 15:13:52 +02:00
|
|
|
* @return -ENOMEM, if not enough resources can be provided for `sock` to be
|
|
|
|
* created.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @return -EPROTONOSUPPORT, if `local != NULL` or `remote != NULL` and
|
|
|
|
* proto is not supported by sock_ip_ep_t::family of @p local or @p
|
|
|
|
* remote.
|
|
|
|
*/
|
|
|
|
int sock_ip_create(sock_ip_t *sock, const sock_ip_ep_t *local,
|
2016-08-19 17:36:58 +02:00
|
|
|
const sock_ip_ep_t *remote, uint8_t proto, uint16_t flags);
|
2016-06-04 12:18:13 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Closes a raw IPv4/IPv6 sock object
|
|
|
|
*
|
|
|
|
* @pre `(sock != NULL)`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
|
|
|
*/
|
|
|
|
void sock_ip_close(sock_ip_t *sock);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Gets the local end point of a raw IPv4/IPv6 sock object
|
|
|
|
*
|
2016-09-28 15:13:52 +02:00
|
|
|
* This gets the local end point of a raw IPv4/IPv6 sock object. Note that this
|
|
|
|
* might not be the same end point you added in @ref sock_ip_create(), but an
|
|
|
|
* end point more suitable for the implementation. Examples for this might be
|
|
|
|
* that if sock_ip_ep_t::netif is given in @ref sock_ip_create(), the
|
|
|
|
* implementation might choose to return the address on this interface the
|
|
|
|
* @p sock is bound to in @p ep's sock_ip_ep_t::addr.
|
|
|
|
*
|
2016-06-04 12:18:13 +02:00
|
|
|
* @pre `(sock != NULL) && (ep != NULL)`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
|
|
|
* @param[out] ep The local end point.
|
|
|
|
*
|
|
|
|
* @return 0 on success.
|
|
|
|
* @return -EADDRNOTAVAIL, when @p sock has no end point bound to it.
|
|
|
|
*/
|
|
|
|
int sock_ip_get_local(sock_ip_t *sock, sock_ip_ep_t *ep);
|
|
|
|
|
|
|
|
/**
|
2019-06-19 14:18:45 +02:00
|
|
|
* @brief Gets the remote end point of a raw IPv4/IPv6 sock object
|
2016-06-04 12:18:13 +02:00
|
|
|
*
|
|
|
|
* @pre `(sock != NULL) && (ep != NULL)`
|
|
|
|
*
|
2016-09-28 15:13:52 +02:00
|
|
|
* This gets the remote end point of a raw IPv4/IPv6 sock object. Note that this
|
|
|
|
* might not be the same end point you added in @ref sock_ip_create(), but an
|
|
|
|
* end point more suitable for the implementation. Examples for this might be
|
|
|
|
* that if sock_ip_ep_t::netif is given in @ref sock_ip_create(), the
|
|
|
|
* implementation might choose to return the address on this interface the
|
|
|
|
* @p sock is bound to in @p ep's sock_ip_ep_t::addr.
|
|
|
|
*
|
2019-06-19 14:18:45 +02:00
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @param[out] ep The remote end point.
|
|
|
|
*
|
|
|
|
* @return 0 on success.
|
|
|
|
* @return -ENOTCONN, when @p sock has no remote end point bound to it.
|
|
|
|
*/
|
|
|
|
int sock_ip_get_remote(sock_ip_t *sock, sock_ip_ep_t *ep);
|
|
|
|
|
2020-07-27 10:57:11 +02:00
|
|
|
/**
|
|
|
|
* @brief Receives a message over IPv4/IPv6 from remote end point
|
|
|
|
*
|
|
|
|
* @pre `(sock != NULL) && (data != NULL) && (max_len > 0)`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
|
|
|
* @param[out] data Pointer where the received data should be stored.
|
|
|
|
* @param[in] max_len Maximum space available at @p data.
|
|
|
|
* @param[in] timeout Timeout for receive in microseconds.
|
|
|
|
* If 0 and no data is available, the function returns
|
|
|
|
* immediately.
|
|
|
|
* May be @ref SOCK_NO_TIMEOUT for no timeout (wait until
|
|
|
|
* data is available).
|
|
|
|
* @param[out] remote Remote end point of the received data.
|
|
|
|
* May be NULL, if it is not required by the application.
|
|
|
|
* @param[out] aux Auxiliary data of the reception.
|
|
|
|
* May be NULL, if it is not required by the application.
|
|
|
|
*
|
|
|
|
* @note Function blocks if no packet is currently waiting.
|
|
|
|
*
|
|
|
|
* @return The number of bytes received on success.
|
|
|
|
* @return 0, if no received data is available, but everything is in order.
|
|
|
|
* @return -EADDRNOTAVAIL, if local of @p sock is not given.
|
|
|
|
* @return -EAGAIN, if @p timeout is `0` and no data is available.
|
|
|
|
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
|
|
|
* initialized (or closed while sock_ip_recv() blocks).
|
|
|
|
* @return -ENOBUFS, if buffer space is not large enough to store received
|
|
|
|
* data.
|
|
|
|
* @return -ENOMEM, if no memory was available to receive @p data.
|
|
|
|
* @return -EPROTO, if source address of received packet did not equal
|
|
|
|
* the remote of @p sock.
|
|
|
|
* @return -ETIMEDOUT, if @p timeout expired.
|
|
|
|
*/
|
|
|
|
ssize_t sock_ip_recv_aux(sock_ip_t *sock, void *data, size_t max_len,
|
|
|
|
uint32_t timeout, sock_ip_ep_t *remote,
|
|
|
|
sock_ip_aux_rx_t *aux);
|
|
|
|
|
2016-06-04 12:18:13 +02:00
|
|
|
/**
|
|
|
|
* @brief Receives a message over IPv4/IPv6 from remote end point
|
|
|
|
*
|
|
|
|
* @pre `(sock != NULL) && (data != NULL) && (max_len > 0)`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
|
|
|
* @param[out] data Pointer where the received data should be stored.
|
|
|
|
* @param[in] max_len Maximum space available at @p data.
|
|
|
|
* @param[in] timeout Timeout for receive in microseconds.
|
2016-10-11 23:23:20 +02:00
|
|
|
* If 0 and no data is available, the function returns
|
|
|
|
* immediately.
|
2016-10-12 17:55:48 +02:00
|
|
|
* May be @ref SOCK_NO_TIMEOUT for no timeout (wait until
|
|
|
|
* data is available).
|
2016-06-04 12:18:13 +02:00
|
|
|
* @param[out] remote Remote end point of the received data.
|
|
|
|
* May be NULL, if it is not required by the application.
|
|
|
|
*
|
|
|
|
* @note Function blocks if no packet is currently waiting.
|
|
|
|
*
|
|
|
|
* @return The number of bytes received on success.
|
|
|
|
* @return 0, if no received data is available, but everything is in order.
|
|
|
|
* @return -EADDRNOTAVAIL, if local of @p sock is not given.
|
2016-10-11 23:23:20 +02:00
|
|
|
* @return -EAGAIN, if @p timeout is `0` and no data is available.
|
2017-06-12 13:53:11 +02:00
|
|
|
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
|
|
|
* initialized (or closed while sock_ip_recv() blocks).
|
2016-06-04 12:18:13 +02:00
|
|
|
* @return -ENOBUFS, if buffer space is not large enough to store received
|
|
|
|
* data.
|
2016-09-02 19:01:10 +02:00
|
|
|
* @return -ENOMEM, if no memory was available to receive @p data.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @return -EPROTO, if source address of received packet did not equal
|
|
|
|
* the remote of @p sock.
|
|
|
|
* @return -ETIMEDOUT, if @p timeout expired.
|
|
|
|
*/
|
2020-07-27 10:57:11 +02:00
|
|
|
static inline ssize_t sock_ip_recv(sock_ip_t *sock, void *data, size_t max_len,
|
|
|
|
uint32_t timeout, sock_ip_ep_t *remote)
|
|
|
|
{
|
|
|
|
return sock_ip_recv_aux(sock, data, max_len, timeout, remote, NULL);
|
|
|
|
}
|
2020-03-11 12:59:20 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Provides stack-internal buffer space containing an IPv4/IPv6
|
|
|
|
* message from remote end point
|
|
|
|
*
|
|
|
|
* @pre `(sock != NULL) && (data != NULL) && (buf_ctx != NULL)`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
|
|
|
* @param[out] data Pointer to a stack-internal buffer space containing the
|
|
|
|
* received data.
|
2020-04-01 12:17:14 +02:00
|
|
|
* @param[in,out] buf_ctx Stack-internal buffer context. If it points to a
|
|
|
|
* `NULL` pointer, the stack returns a new buffer space
|
|
|
|
* for a new packet. If it does not point to a `NULL`
|
|
|
|
* pointer, an existing context is assumed to get a next
|
|
|
|
* segment in a buffer.
|
2020-03-11 12:59:20 +01:00
|
|
|
* @param[in] timeout Timeout for receive in microseconds.
|
|
|
|
* If 0 and no data is available, the function returns
|
|
|
|
* immediately.
|
|
|
|
* May be @ref SOCK_NO_TIMEOUT for no timeout (wait until
|
|
|
|
* data is available).
|
|
|
|
* @param[out] remote Remote end point of the received data.
|
|
|
|
* May be NULL, if it is not required by the application.
|
2020-07-27 10:57:11 +02:00
|
|
|
* @param[out] aux Auxiliary data of the reception.
|
|
|
|
* May be NULL, if it is not required by the application.
|
2020-03-11 12:59:20 +01:00
|
|
|
*
|
2020-04-01 12:21:27 +02:00
|
|
|
* @experimental This function is quite new, not implemented for all stacks
|
|
|
|
* yet, and may be subject to sudden API changes. Do not use in
|
|
|
|
* production if this is unacceptable.
|
|
|
|
*
|
2020-03-11 12:59:20 +01:00
|
|
|
* @note Function blocks if no packet is currently waiting.
|
|
|
|
*
|
2020-04-01 12:17:14 +02:00
|
|
|
* @return The number of bytes received on success. May not be the complete
|
|
|
|
* payload. Continue calling with the returned `buf_ctx` to get more
|
|
|
|
* buffers until result is 0 or an error.
|
2020-03-11 12:59:20 +01:00
|
|
|
* @return 0, if no received data is available, but everything is in order.
|
2020-04-01 12:17:14 +02:00
|
|
|
* If @p buf_ctx was provided, it was released.
|
2020-03-11 12:59:20 +01:00
|
|
|
* @return -EADDRNOTAVAIL, if local of @p sock is not given.
|
|
|
|
* @return -EAGAIN, if @p timeout is `0` and no data is available.
|
|
|
|
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
|
|
|
* initialized (or closed while sock_ip_recv() blocks).
|
|
|
|
* @return -ENOMEM, if no memory was available to receive @p data.
|
|
|
|
* @return -EPROTO, if source address of received packet did not equal
|
|
|
|
* the remote of @p sock.
|
|
|
|
* @return -ETIMEDOUT, if @p timeout expired.
|
|
|
|
*/
|
2020-07-27 10:57:11 +02:00
|
|
|
ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
|
|
|
|
uint32_t timeout, sock_ip_ep_t *remote,
|
|
|
|
sock_ip_aux_rx_t *aux);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Provides stack-internal buffer space containing an IPv4/IPv6
|
|
|
|
* message from remote end point
|
|
|
|
*
|
|
|
|
* @pre `(sock != NULL) && (data != NULL) && (buf_ctx != NULL)`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object.
|
|
|
|
* @param[out] data Pointer to a stack-internal buffer space containing the
|
|
|
|
* received data.
|
|
|
|
* @param[in,out] buf_ctx Stack-internal buffer context. If it points to a
|
|
|
|
* `NULL` pointer, the stack returns a new buffer space
|
|
|
|
* for a new packet. If it does not point to a `NULL`
|
|
|
|
* pointer, an existing context is assumed to get a next
|
|
|
|
* segment in a buffer.
|
|
|
|
* @param[in] timeout Timeout for receive in microseconds.
|
|
|
|
* If 0 and no data is available, the function returns
|
|
|
|
* immediately.
|
|
|
|
* May be @ref SOCK_NO_TIMEOUT for no timeout (wait until
|
|
|
|
* data is available).
|
|
|
|
* @param[out] remote Remote end point of the received data.
|
|
|
|
* May be NULL, if it is not required by the application.
|
|
|
|
*
|
|
|
|
* @experimental This function is quite new, not implemented for all stacks
|
|
|
|
* yet, and may be subject to sudden API changes. Do not use in
|
|
|
|
* production if this is unacceptable.
|
|
|
|
*
|
|
|
|
* @note Function blocks if no packet is currently waiting.
|
|
|
|
*
|
|
|
|
* @return The number of bytes received on success. May not be the complete
|
|
|
|
* payload. Continue calling with the returned `buf_ctx` to get more
|
|
|
|
* buffers until result is 0 or an error.
|
|
|
|
* @return 0, if no received data is available, but everything is in order.
|
|
|
|
* If @p buf_ctx was provided, it was released.
|
|
|
|
* @return -EADDRNOTAVAIL, if local of @p sock is not given.
|
|
|
|
* @return -EAGAIN, if @p timeout is `0` and no data is available.
|
|
|
|
* @return -EINVAL, if @p remote is invalid or @p sock is not properly
|
|
|
|
* initialized (or closed while sock_ip_recv() blocks).
|
|
|
|
* @return -ENOMEM, if no memory was available to receive @p data.
|
|
|
|
* @return -EPROTO, if source address of received packet did not equal
|
|
|
|
* the remote of @p sock.
|
|
|
|
* @return -ETIMEDOUT, if @p timeout expired.
|
|
|
|
*/
|
|
|
|
static inline ssize_t sock_ip_recv_buf(sock_ip_t *sock,
|
|
|
|
void **data, void **buf_ctx,
|
|
|
|
uint32_t timeout, sock_ip_ep_t *remote)
|
|
|
|
{
|
|
|
|
return sock_ip_recv_buf_aux(sock, data, buf_ctx, timeout, remote, NULL);
|
|
|
|
}
|
2016-06-04 12:18:13 +02:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Sends a message over IPv4/IPv6 to remote end point
|
|
|
|
*
|
|
|
|
* @pre `((sock != NULL || remote != NULL)) && (if (len != 0): (data != NULL))`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object. May be NULL.
|
|
|
|
* A sensible local end point should be selected by the
|
2016-09-28 15:13:52 +02:00
|
|
|
* implementation in that case.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @param[in] data Pointer where the received data should be stored.
|
|
|
|
* May be `NULL` if `len == 0`.
|
|
|
|
* @param[in] len Maximum space available at @p data.
|
2016-09-28 15:13:52 +02:00
|
|
|
* @param[in] proto Protocol to use in the packet sent, in case
|
2016-08-25 16:02:45 +02:00
|
|
|
* `sock == NULL`. If `sock != NULL` this parameter will be
|
|
|
|
* ignored.
|
2016-09-28 15:13:52 +02:00
|
|
|
* @param[in] remote Remote end point for the sent data.
|
2016-06-04 12:18:13 +02:00
|
|
|
* May be `NULL`, if @p sock has a remote end point.
|
|
|
|
* sock_ip_ep_t::family may be AF_UNSPEC, if local
|
|
|
|
* end point of @p sock provides this information.
|
2020-07-27 10:57:11 +02:00
|
|
|
* @param[out] aux Auxiliary data for the transmission.
|
|
|
|
* May be `NULL` if not needed by the caller.
|
2016-06-04 12:18:13 +02:00
|
|
|
*
|
2016-09-28 15:13:52 +02:00
|
|
|
* @return The number of bytes sent on success.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @return -EAFNOSUPPORT, if `remote != NULL` and sock_ip_ep_t::family of
|
|
|
|
* @p remote is != AF_UNSPEC and not supported.
|
2016-10-05 17:14:39 +02:00
|
|
|
* @return -EINVAL, if sock_ip_ep_t::addr of @p remote is an invalid address.
|
|
|
|
* @return -EINVAL, if sock_ip_ep_t::netif of @p remote is not a
|
|
|
|
* valid interface or contradicts the local interface of @p sock.
|
2016-09-02 19:01:10 +02:00
|
|
|
* @return -EHOSTUNREACH, if @p remote or remote end point of @p sock is not
|
|
|
|
* reachable.
|
2016-06-04 12:18:13 +02:00
|
|
|
* @return -ENOMEM, if no memory was available to send @p data.
|
|
|
|
* @return -ENOTCONN, if `remote == NULL`, but @p sock has no remote end point.
|
2016-08-25 16:02:45 +02:00
|
|
|
* @return -EPROTOTYPE, if `sock == NULL` and @p proto is not by
|
|
|
|
* sock_ip_ep_t::family of @p remote.
|
2016-06-04 12:18:13 +02:00
|
|
|
*/
|
2020-07-27 10:57:11 +02:00
|
|
|
ssize_t sock_ip_send_aux(sock_ip_t *sock, const void *data, size_t len,
|
|
|
|
uint8_t proto, const sock_ip_ep_t *remote,
|
|
|
|
sock_ip_aux_tx_t *aux);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Sends a message over IPv4/IPv6 to remote end point
|
|
|
|
*
|
|
|
|
* @pre `((sock != NULL || remote != NULL)) && (if (len != 0): (data != NULL))`
|
|
|
|
*
|
|
|
|
* @param[in] sock A raw IPv4/IPv6 sock object. May be NULL.
|
|
|
|
* A sensible local end point should be selected by the
|
|
|
|
* implementation in that case.
|
|
|
|
* @param[in] data Pointer where the received data should be stored.
|
|
|
|
* May be `NULL` if `len == 0`.
|
|
|
|
* @param[in] len Maximum space available at @p data.
|
|
|
|
* @param[in] proto Protocol to use in the packet sent, in case
|
|
|
|
* `sock == NULL`. If `sock != NULL` this parameter will be
|
|
|
|
* ignored.
|
|
|
|
* @param[in] remote Remote end point for the sent data.
|
|
|
|
* May be `NULL`, if @p sock has a remote end point.
|
|
|
|
* sock_ip_ep_t::family may be AF_UNSPEC, if local
|
|
|
|
* end point of @p sock provides this information.
|
|
|
|
*
|
|
|
|
* @return The number of bytes sent on success.
|
|
|
|
* @return -EAFNOSUPPORT, if `remote != NULL` and sock_ip_ep_t::family of
|
|
|
|
* @p remote is != AF_UNSPEC and not supported.
|
|
|
|
* @return -EINVAL, if sock_ip_ep_t::addr of @p remote is an invalid address.
|
|
|
|
* @return -EINVAL, if sock_ip_ep_t::netif of @p remote is not a
|
|
|
|
* valid interface or contradicts the local interface of @p sock.
|
|
|
|
* @return -EHOSTUNREACH, if @p remote or remote end point of @p sock is not
|
|
|
|
* reachable.
|
|
|
|
* @return -ENOMEM, if no memory was available to send @p data.
|
|
|
|
* @return -ENOTCONN, if `remote == NULL`, but @p sock has no remote end point.
|
|
|
|
* @return -EPROTOTYPE, if `sock == NULL` and @p proto is not by
|
|
|
|
* sock_ip_ep_t::family of @p remote.
|
|
|
|
*/
|
|
|
|
static inline ssize_t sock_ip_send(sock_ip_t *sock,
|
|
|
|
const void *data, size_t len,
|
|
|
|
uint8_t proto, const sock_ip_ep_t *remote)
|
|
|
|
{
|
|
|
|
return sock_ip_send_aux(sock, data, len, proto, remote, NULL);
|
|
|
|
}
|
2016-06-04 12:18:13 +02:00
|
|
|
|
2016-08-19 16:17:35 +02:00
|
|
|
#include "sock_types.h"
|
2016-06-04 12:18:13 +02:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2017-01-18 13:00:05 +01:00
|
|
|
#endif /* NET_SOCK_IP_H */
|
2016-06-04 12:18:13 +02:00
|
|
|
/** @} */
|