sys/net/gnrc: Implement sock_aux_local

Provide address the IP packet / UDP datagram was received on in the auxiliary
data, if module sock_aux_local is used.
This commit is contained in:
Marian Buschsieweke 2020-07-27 16:07:19 +02:00
parent 9d46bc7d7f
commit 1d69f067d1
No known key found for this signature in database
GPG Key ID: 61F64C6599B1539F
4 changed files with 63 additions and 4 deletions

View File

@ -89,8 +89,11 @@ void gnrc_sock_create(gnrc_sock_reg_t *reg, gnrc_nettype_t type, uint32_t demux_
} }
ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out, ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out,
uint32_t timeout, sock_ip_ep_t *remote) uint32_t timeout, sock_ip_ep_t *remote,
gnrc_sock_recv_aux_t aux)
{ {
/* only used when some sock_aux_% module is used */
(void)aux;
gnrc_pktsnip_t *pkt, *netif; gnrc_pktsnip_t *pkt, *netif;
msg_t msg; msg_t msg;
@ -150,6 +153,12 @@ ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt_out,
assert(ipv6_hdr != NULL); assert(ipv6_hdr != NULL);
memcpy(&remote->addr, &ipv6_hdr->src, sizeof(ipv6_addr_t)); memcpy(&remote->addr, &ipv6_hdr->src, sizeof(ipv6_addr_t));
remote->family = AF_INET6; remote->family = AF_INET6;
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
if (aux.local != NULL) {
memcpy(&aux.local->addr, &ipv6_hdr->dst, sizeof(ipv6_addr_t));
aux.local->family = AF_INET6;
}
#endif /* MODULE_SOCK_AUX_LOCAL */
netif = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF); netif = gnrc_pktsnip_search_type(pkt, GNRC_NETTYPE_NETIF);
if (netif == NULL) { if (netif == NULL) {
remote->netif = SOCK_ADDR_ANY_NETIF; remote->netif = SOCK_ADDR_ANY_NETIF;

View File

@ -55,6 +55,33 @@ extern "C" {
*/ */
#define GNRC_SOCK_DYN_PORTRANGE_ERR (0) #define GNRC_SOCK_DYN_PORTRANGE_ERR (0)
/**
* @brief Structure to retrieve auxiliary data from @ref gnrc_sock_recv
*
* @details The members of this function depend on the modules used
* @internal
*/
typedef struct {
#if IS_USED(MODULE_SOCK_AUX_LOCAL) || DOXYGEN
/**
* @brief local IP address PDU was received on
*
* This member is only present if module `sock_aux_local` is used.
*/
sock_ip_ep_t *local;
#endif
#if !IS_USED(MODULE_SOCK_AUX_LOCAL) || DOXYGEN
/**
* @brief Workaround in case no `sock_aux_%` module is used
*
* Empty structures are only allowed with a GNU extension. For portability,
* this member is present if and only if this structure would be otherwise
* empty.
*/
uint8_t this_struct_is_not_empty;
#endif
} gnrc_sock_recv_aux_t;
/** /**
* @brief Internal helper functions for GNRC * @brief Internal helper functions for GNRC
* @internal * @internal
@ -116,7 +143,7 @@ void gnrc_sock_create(gnrc_sock_reg_t *reg, gnrc_nettype_t type, uint32_t demux_
* @internal * @internal
*/ */
ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt, uint32_t timeout, ssize_t gnrc_sock_recv(gnrc_sock_reg_t *reg, gnrc_pktsnip_t **pkt, uint32_t timeout,
sock_ip_ep_t *remote); sock_ip_ep_t *remote, gnrc_sock_recv_aux_t aux);
/** /**
* @brief Send a packet internally * @brief Send a packet internally

View File

@ -117,6 +117,7 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
gnrc_pktsnip_t *pkt; gnrc_pktsnip_t *pkt;
sock_ip_ep_t tmp; sock_ip_ep_t tmp;
int res; int res;
gnrc_sock_recv_aux_t _aux = { 0 };
assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL)); assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL));
if (*buf_ctx != NULL) { if (*buf_ctx != NULL) {
@ -129,7 +130,12 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
tmp.family = sock->local.family; tmp.family = sock->local.family;
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp); #if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
_aux.local = &aux->local;
}
#endif
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, _aux);
if (res < 0) { if (res < 0) {
return res; return res;
} }
@ -146,6 +152,11 @@ ssize_t sock_ip_recv_buf_aux(sock_ip_t *sock, void **data, void **buf_ctx,
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return -EPROTO; return -EPROTO;
} }
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
aux->flags &= ~(SOCK_AUX_GET_LOCAL);
}
#endif
*data = pkt->data; *data = pkt->data;
*buf_ctx = pkt; *buf_ctx = pkt;
res = (int)pkt->size; res = (int)pkt->size;

View File

@ -206,6 +206,7 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
udp_hdr_t *hdr; udp_hdr_t *hdr;
sock_ip_ep_t tmp; sock_ip_ep_t tmp;
int res; int res;
gnrc_sock_recv_aux_t _aux = { 0 };
assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL)); assert((sock != NULL) && (data != NULL) && (buf_ctx != NULL));
if (*buf_ctx != NULL) { if (*buf_ctx != NULL) {
@ -218,7 +219,12 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
return -EADDRNOTAVAIL; return -EADDRNOTAVAIL;
} }
tmp.family = sock->local.family; tmp.family = sock->local.family;
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp); #if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
_aux.local = (sock_ip_ep_t *)&aux->local;
}
#endif
res = gnrc_sock_recv((gnrc_sock_reg_t *)sock, &pkt, timeout, &tmp, _aux);
if (res < 0) { if (res < 0) {
return res; return res;
} }
@ -240,6 +246,12 @@ ssize_t sock_udp_recv_buf_aux(sock_udp_t *sock, void **data, void **buf_ctx,
gnrc_pktbuf_release(pkt); gnrc_pktbuf_release(pkt);
return -EPROTO; return -EPROTO;
} }
#if IS_USED(MODULE_SOCK_AUX_LOCAL)
if ((aux != NULL) && (aux->flags & SOCK_AUX_GET_LOCAL)) {
aux->flags &= ~SOCK_AUX_GET_LOCAL;
aux->local.port = sock->local.port;
}
#endif
*data = pkt->data; *data = pkt->data;
*buf_ctx = pkt; *buf_ctx = pkt;
res = (int)pkt->size; res = (int)pkt->size;