1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

gcoap_forward_proxy: add CoAPS support

This commit is contained in:
Martine Lenders 2022-05-12 18:53:43 +02:00
parent 632837a0a8
commit 194e676e6d
No known key found for this signature in database
GPG Key ID: 2134D77A5336DD80
4 changed files with 50 additions and 23 deletions

View File

@ -473,6 +473,9 @@ endif
ifneq (,$(filter gcoap_forward_proxy,$(USEMODULE))) ifneq (,$(filter gcoap_forward_proxy,$(USEMODULE)))
USEMODULE += gcoap USEMODULE += gcoap
USEMODULE += uri_parser USEMODULE += uri_parser
ifneq (,$(filter gcoap_dtls,$(USEMODULE)))
USEMODULE += gcoap_forward_proxy_thread
endif
endif endif
ifneq (,$(filter gcoap_forward_proxy_thread,$(USEMODULE))) ifneq (,$(filter gcoap_forward_proxy_thread,$(USEMODULE)))

View File

@ -60,6 +60,7 @@ void gcoap_forward_proxy_init(void);
* @param[in] pkt Packet to parse * @param[in] pkt Packet to parse
* @param[in] client Endpoint of the client * @param[in] client Endpoint of the client
* @param[in] local Local endpoint * @param[in] local Local endpoint
* @param[in] client_tl [Socket type](@ref gcoap_socket_type_t) of the client
* *
* @return 0 if parsing was successful * @return 0 if parsing was successful
* @return -ENOTSUP if the forward proxy is not compiled in * @return -ENOTSUP if the forward proxy is not compiled in
@ -67,7 +68,8 @@ void gcoap_forward_proxy_init(void);
* @return -EINVAL if Proxy-Uri is malformed * @return -EINVAL if Proxy-Uri is malformed
*/ */
int gcoap_forward_proxy_request_process(coap_pkt_t *pkt, int gcoap_forward_proxy_request_process(coap_pkt_t *pkt,
const sock_udp_ep_t *client, const sock_udp_ep_t *local); const sock_udp_ep_t *client, const sock_udp_ep_t *local,
gcoap_socket_type_t client_tl);
/** /**
* @brief Finds the memo for an outstanding request within the * @brief Finds the memo for an outstanding request within the

View File

@ -71,6 +71,9 @@ const coap_resource_t forward_proxy_resources[] = {
gcoap_listener_t forward_proxy_listener = { gcoap_listener_t forward_proxy_listener = {
&forward_proxy_resources[0], &forward_proxy_resources[0],
ARRAY_SIZE(forward_proxy_resources), ARRAY_SIZE(forward_proxy_resources),
#if IS_USED(MODULE_GCOAP_DTLS)
GCOAP_SOCKET_TYPE_DTLS |
#endif
GCOAP_SOCKET_TYPE_UDP, GCOAP_SOCKET_TYPE_UDP,
NULL, NULL,
NULL, NULL,
@ -96,7 +99,7 @@ void gcoap_forward_proxy_init(void)
} }
} }
static client_ep_t *_allocate_client_ep(const sock_udp_ep_t *ep) static client_ep_t *_allocate_client_ep(const sock_udp_ep_t *ep, gcoap_socket_type_t tl)
{ {
client_ep_t *cep; client_ep_t *cep;
for (cep = _client_eps; for (cep = _client_eps;
@ -106,6 +109,7 @@ static client_ep_t *_allocate_client_ep(const sock_udp_ep_t *ep)
_cep_set_in_use(cep); _cep_set_in_use(cep);
_cep_set_req_etag(cep, NULL, 0); _cep_set_req_etag(cep, NULL, 0);
memcpy(&cep->ep, ep, sizeof(*ep)); memcpy(&cep->ep, ep, sizeof(*ep));
cep->client_tl = tl;
DEBUG("Client_ep is allocated %p\n", (void *)cep); DEBUG("Client_ep is allocated %p\n", (void *)cep);
return cep; return cep;
} }
@ -144,7 +148,9 @@ static ssize_t _forward_proxy_handler(coap_pkt_t *pdu, uint8_t *buf,
const sock_udp_ep_t *remote = coap_request_ctx_get_remote_udp(ctx); const sock_udp_ep_t *remote = coap_request_ctx_get_remote_udp(ctx);
const sock_udp_ep_t *local = coap_request_ctx_get_local_udp(ctx); const sock_udp_ep_t *local = coap_request_ctx_get_local_udp(ctx);
pdu_len = gcoap_forward_proxy_request_process(pdu, remote, local); pdu_len = gcoap_forward_proxy_request_process(
pdu, remote, local, (gcoap_socket_type_t)ctx->tl_type
);
/* Out of memory, reply with 5.00 */ /* Out of memory, reply with 5.00 */
if (pdu_len == -ENOMEM) { if (pdu_len == -ENOMEM) {
@ -162,24 +168,25 @@ static ssize_t _forward_proxy_handler(coap_pkt_t *pdu, uint8_t *buf,
return pdu_len; return pdu_len;
} }
static bool _parse_endpoint(sock_udp_ep_t *remote, static gcoap_socket_type_t _parse_endpoint(sock_udp_ep_t *remote,
uri_parser_result_t *urip) uri_parser_result_t *urip)
{ {
char scratch[8]; char scratch[8];
ipv6_addr_t addr; ipv6_addr_t addr;
gcoap_socket_type_t res = GCOAP_SOCKET_TYPE_UDP;
remote->family = AF_INET6; remote->family = AF_INET6;
/* support IPv6 only for now */ /* support IPv6 only for now */
if (!urip->ipv6addr) { if (!urip->ipv6addr) {
return false; return GCOAP_SOCKET_TYPE_UNDEF;
} }
/* check for interface */ /* check for interface */
if (urip->zoneid) { if (urip->zoneid) {
/* only works with integer based zoneids */ /* only works with integer based zoneids */
if (urip->zoneid_len > (ARRAY_SIZE(scratch) - 1)) { if (urip->zoneid_len > (ARRAY_SIZE(scratch) - 1)) {
return false; return GCOAP_SOCKET_TYPE_UNDEF;
} }
memcpy(scratch, urip->zoneid, urip->zoneid_len); memcpy(scratch, urip->zoneid, urip->zoneid_len);
@ -189,7 +196,7 @@ static bool _parse_endpoint(sock_udp_ep_t *remote,
int pid = atoi(scratch); int pid = atoi(scratch);
if (gnrc_netif_get_by_pid(pid) == NULL) { if (gnrc_netif_get_by_pid(pid) == NULL) {
return false; return GCOAP_SOCKET_TYPE_UNDEF;
} }
remote->netif = pid; remote->netif = pid;
} }
@ -206,35 +213,42 @@ static bool _parse_endpoint(sock_udp_ep_t *remote,
/* parse destination address */ /* parse destination address */
if (ipv6_addr_from_buf(&addr, urip->ipv6addr, urip->ipv6addr_len) == NULL) { if (ipv6_addr_from_buf(&addr, urip->ipv6addr, urip->ipv6addr_len) == NULL) {
return false; return GCOAP_SOCKET_TYPE_UNDEF;
} }
if ((remote->netif == SOCK_ADDR_ANY_NETIF) && if ((remote->netif == SOCK_ADDR_ANY_NETIF) &&
ipv6_addr_is_link_local(&addr)) { ipv6_addr_is_link_local(&addr)) {
return false; return GCOAP_SOCKET_TYPE_UNDEF;
} }
memcpy(&remote->addr.ipv6[0], &addr.u8[0], sizeof(addr.u8)); memcpy(&remote->addr.ipv6[0], &addr.u8[0], sizeof(addr.u8));
bool is_coaps = (IS_USED(MODULE_GCOAP_DTLS) && !strncmp(urip->scheme, "coaps", 5));
if (is_coaps) {
res = GCOAP_SOCKET_TYPE_DTLS;
}
if (urip->port != 0) { if (urip->port != 0) {
remote->port = urip->port; remote->port = urip->port;
} }
else if (!strncmp(urip->scheme, "coaps", 5)) { else if (is_coaps) {
remote->port = COAPS_PORT; remote->port = COAPS_PORT;
} }
else { else {
remote->port = COAP_PORT; remote->port = COAP_PORT;
} }
return true; return res;
} }
static ssize_t _dispatch_msg(const void *buf, size_t len, sock_udp_ep_t *remote, static ssize_t _dispatch_msg(const void *buf,
const sock_udp_ep_t *local) size_t len,
sock_udp_ep_t *remote,
sock_udp_ep_t *local,
gcoap_socket_type_t socket_type)
{ {
/* Yes it's not a request -- but turns out there is nothing in /* Yes it's not a request -- but turns out there is nothing in
* gcoap_req_send that is actually request specific, especially if we * gcoap_req_send that is actually request specific, especially if we
* don't assign a callback. */ * don't assign a callback. */
ssize_t res = gcoap_req_send(buf, len, remote, local, NULL, NULL, ssize_t res = gcoap_req_send(buf, len, remote, local, NULL, NULL,
GCOAP_SOCKET_TYPE_UDP); socket_type);
if (res <= 0) { if (res <= 0) {
DEBUG("gcoap_forward_proxy: unable to dispatch message: %d\n", -res); DEBUG("gcoap_forward_proxy: unable to dispatch message: %d\n", -res);
} }
@ -254,7 +268,7 @@ static void _send_empty_ack(event_t *event)
/* Flipping byte order as unlike in the other places where mid is /* Flipping byte order as unlike in the other places where mid is
* used, coap_build_hdr would actually flip it back */ * used, coap_build_hdr would actually flip it back */
coap_build_hdr(&buf, COAP_TYPE_ACK, NULL, 0, 0, ntohs(cep->mid)); coap_build_hdr(&buf, COAP_TYPE_ACK, NULL, 0, 0, ntohs(cep->mid));
_dispatch_msg(&buf, sizeof(buf), &cep->ep, &cep->proxy_ep); _dispatch_msg(&buf, sizeof(buf), &cep->ep, &cep->proxy_ep, cep->client_tl);
} }
static void _set_response_type(coap_pkt_t *pdu, uint8_t resp_type) static void _set_response_type(coap_pkt_t *pdu, uint8_t resp_type)
@ -318,7 +332,7 @@ static void _forward_resp_handler(const gcoap_request_memo_t *memo,
} }
_set_response_type(pdu, _cep_get_response_type(cep)); _set_response_type(pdu, _cep_get_response_type(cep));
/* don't use buf_len here, in case the above `gcoap_resp_init`s changed `pdu` */ /* don't use buf_len here, in case the above `gcoap_resp_init`s changed `pdu` */
_dispatch_msg(pdu->hdr, coap_get_total_len(pdu), &cep->ep, &cep->proxy_ep); _dispatch_msg(pdu->hdr, coap_get_total_len(pdu), &cep->ep, &cep->proxy_ep, cep->client_tl);
_free_client_ep(cep); _free_client_ep(cep);
} }
@ -411,7 +425,7 @@ int gcoap_forward_proxy_req_send(client_ep_t *cep)
int len; int len;
if ((len = gcoap_req_send((uint8_t *)cep->pdu.hdr, coap_get_total_len(&cep->pdu), if ((len = gcoap_req_send((uint8_t *)cep->pdu.hdr, coap_get_total_len(&cep->pdu),
&cep->server_ep, NULL, _forward_resp_handler, cep, &cep->server_ep, NULL, _forward_resp_handler, cep,
GCOAP_SOCKET_TYPE_UNDEF)) <= 0) { cep->server_tl)) <= 0) {
DEBUG("gcoap_forward_proxy_req_send(): gcoap_req_send failed %d\n", len); DEBUG("gcoap_forward_proxy_req_send(): gcoap_req_send failed %d\n", len);
_free_client_ep(cep); _free_client_ep(cep);
} }
@ -422,10 +436,12 @@ static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt,
client_ep_t *client_ep, client_ep_t *client_ep,
uri_parser_result_t *urip) uri_parser_result_t *urip)
{ {
gcoap_socket_type_t server_tl;
ssize_t len; ssize_t len;
gcoap_request_memo_t *memo = NULL; gcoap_request_memo_t *memo = NULL;
if (!_parse_endpoint(&client_ep->server_ep, urip)) { if ((server_tl = _parse_endpoint(&client_ep->server_ep, urip)) == GCOAP_SOCKET_TYPE_UNDEF) {
_free_client_ep(client_ep); _free_client_ep(client_ep);
return -EINVAL; return -EINVAL;
} }
@ -465,6 +481,7 @@ static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt,
_free_client_ep(client_ep); _free_client_ep(client_ep);
return -EINVAL; return -EINVAL;
} }
client_ep->server_tl = server_tl;
if (IS_USED(MODULE_GCOAP_FORWARD_PROXY_THREAD)) { if (IS_USED(MODULE_GCOAP_FORWARD_PROXY_THREAD)) {
/* WORKAROUND: DTLS communication is blocking the gcoap thread, /* WORKAROUND: DTLS communication is blocking the gcoap thread,
* therefore the communication should be handled in the proxy thread */ * therefore the communication should be handled in the proxy thread */
@ -482,12 +499,14 @@ static int _gcoap_forward_proxy_via_coap(coap_pkt_t *client_pkt,
} }
int gcoap_forward_proxy_request_process(coap_pkt_t *pkt, int gcoap_forward_proxy_request_process(coap_pkt_t *pkt,
const sock_udp_ep_t *client, const sock_udp_ep_t *local) { const sock_udp_ep_t *client,
const sock_udp_ep_t *local,
gcoap_socket_type_t client_tl) {
char *uri; char *uri;
uri_parser_result_t urip; uri_parser_result_t urip;
ssize_t optlen = 0; ssize_t optlen = 0;
client_ep_t *cep = _allocate_client_ep(client); client_ep_t *cep = _allocate_client_ep(client, client_tl);
cep->proxy_ep = local ? *local : (sock_udp_ep_t){ 0 }; cep->proxy_ep = local ? *local : (sock_udp_ep_t){ 0 };
if (!cep) { if (!cep) {
return -ENOMEM; return -ENOMEM;
@ -517,7 +536,8 @@ int gcoap_forward_proxy_request_process(coap_pkt_t *pkt,
/* target is using CoAP */ /* target is using CoAP */
if (!strncmp("coap", urip.scheme, urip.scheme_len) || if (!strncmp("coap", urip.scheme, urip.scheme_len) ||
!strncmp("coaps", urip.scheme, urip.scheme_len)) { (IS_USED(MODULE_GCOAP_DTLS) &&
!strncmp("coaps", urip.scheme, urip.scheme_len))) {
/* client context ownership is passed to gcoap_forward_proxy_req_send() */ /* client context ownership is passed to gcoap_forward_proxy_req_send() */
int res = _gcoap_forward_proxy_via_coap(pkt, cep, &urip); int res = _gcoap_forward_proxy_via_coap(pkt, cep, &urip);
if (res < 0) { if (res < 0) {

View File

@ -41,6 +41,8 @@ typedef struct {
sock_udp_ep_t server_ep; /**< forward Server endpoint */ sock_udp_ep_t server_ep; /**< forward Server endpoint */
sock_udp_ep_t ep; /**< client endpoint */ sock_udp_ep_t ep; /**< client endpoint */
sock_udp_ep_t proxy_ep; /**< proxy endpoint */ sock_udp_ep_t proxy_ep; /**< proxy endpoint */
gcoap_socket_type_t server_tl; /**< forward server socket type */
gcoap_socket_type_t client_tl; /**< client socket type */
uint16_t mid; /**< message ID */ uint16_t mid; /**< message ID */
uint8_t flags; /**< client flags */ uint8_t flags; /**< client flags */
#if IS_USED(MODULE_NANOCOAP_CACHE) #if IS_USED(MODULE_NANOCOAP_CACHE)