pex: indicate refused update requests
authorFelix Fietkau <nbd@nbd.name>
Tue, 27 May 2025 09:39:10 +0000 (11:39 +0200)
committerFelix Fietkau <nbd@nbd.name>
Fri, 30 May 2025 17:42:41 +0000 (19:42 +0200)
This is used, in case an unknown peer requests a network update.
That way the peer can know that it is not considered to be a part of
the network by the remote peer.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
network.h
pex-msg.c
pex-msg.h
pex.c
ubus.c

index aa45b6b27ae642e51a59bb6880c0313f722ede8b..57450cc088f7951ca767ec3d33c987d6d07e010c 100644 (file)
--- a/network.h
+++ b/network.h
@@ -57,6 +57,7 @@ struct network {
        size_t net_data_len;
        uint64_t net_data_version;
        int num_net_queries;
+       unsigned int update_refused;
 
        struct uloop_timeout reload_timer;
 
index fef550509033270c1c9e245d6fbd69ce676a70b3..34b3bb99b889ff5eb82fcefdb4a1bd2052330cff 100644 (file)
--- a/pex-msg.c
+++ b/pex-msg.c
@@ -480,6 +480,8 @@ void *pex_msg_update_response_recv(const void *data, int len, enum pex_opcode op
        uint8_t enc_key[CURVE25519_KEY_SIZE];
        void *ret;
 
+       if (timestamp)
+               *timestamp = 0;
        *data_len = 0;
        if (op == PEX_MSG_UPDATE_RESPONSE) {
                const struct pex_update_response *res = data;
@@ -510,7 +512,8 @@ void *pex_msg_update_response_recv(const void *data, int len, enum pex_opcode op
 
                data += sizeof(*res);
                len -= sizeof(*res);
-       } else if (op == PEX_MSG_UPDATE_RESPONSE_NO_DATA) {
+       } else if (op == PEX_MSG_UPDATE_RESPONSE_NO_DATA ||
+                  op == PEX_MSG_UPDATE_RESPONSE_REFUSED) {
                const struct pex_update_response_no_data *res = data;
 
                if (len < sizeof(*res) || !res->cur_version)
@@ -520,6 +523,8 @@ void *pex_msg_update_response_recv(const void *data, int len, enum pex_opcode op
                if (!ctx)
                        return NULL;
 
+               if (timestamp)
+                       *timestamp = be64_to_cpu(res->cur_version);
                goto error;
        } else {
                return NULL;
index 36aade2b02f6b0c8208668d2f6d74a879585453a..473d7edeb587e2ef977ae71b973a9226453a7f33 100644 (file)
--- a/pex-msg.h
+++ b/pex-msg.h
@@ -26,6 +26,7 @@ enum pex_opcode {
        PEX_MSG_ENDPOINT_NOTIFY,
        PEX_MSG_ENDPOINT_PORT_NOTIFY,
        PEX_MSG_ENROLL,
+       PEX_MSG_UPDATE_RESPONSE_REFUSED,
 };
 
 #define PEX_ID_LEN             8
diff --git a/pex.c b/pex.c
index cfd238fcd111d714ccb27c2ac88a75b12f09340a..a1c602dc0d055adfc723a1874730d76657ab84d6 100644 (file)
--- a/pex.c
+++ b/pex.c
@@ -572,7 +572,7 @@ network_pex_recv_update_request(struct network *net, struct network_peer *peer,
 
        D("receive update request, local version=%"PRIu64", remote version=%"PRIu64, net->net_data_version, req_version);
 
-       if (req_version && req_version >= net->net_data_version) {
+       if (peer && req_version && req_version >= net->net_data_version) {
                struct pex_update_response_no_data *res;
 
                pex_msg_init_ext(net, PEX_MSG_UPDATE_RESPONSE_NO_DATA, !!addr);
@@ -584,6 +584,15 @@ network_pex_recv_update_request(struct network *net, struct network_peer *peer,
 
        if (req_version > net->net_data_version)
                network_pex_send_update_request(net, peer, addr);
+       else if (!peer && net->net_data_len) {
+               struct pex_update_response_no_data *res;
+
+               pex_msg_init_ext(net, PEX_MSG_UPDATE_RESPONSE_REFUSED, !!addr);
+               res = pex_msg_append(sizeof(*res));
+               res->req_id = req->req_id;
+               res->cur_version = cpu_to_be64(net->net_data_version);
+               pex_msg_send_ext(net, peer, addr);
+       }
 
        if (!peer || !net->net_data_len)
                return;
@@ -628,8 +637,12 @@ network_pex_recv_update_response(struct network *net, const uint8_t *data, size_
                return;
 
        net_data = pex_msg_update_response_recv(data, len, op, &net_data_len, &version);
-       if (!net_data)
+       if (!net_data) {
+               if (op == PEX_MSG_UPDATE_RESPONSE_REFUSED && net_data_len == -1 &&
+                   version > net->net_data_version)
+                       net->update_refused++;
                return;
+       }
 
        if (version <= net->net_data_version) {
                free(net_data);
@@ -684,6 +697,7 @@ network_pex_recv(struct network *net, struct network_peer *peer, struct pex_hdr
        case PEX_MSG_UPDATE_RESPONSE:
        case PEX_MSG_UPDATE_RESPONSE_DATA:
        case PEX_MSG_UPDATE_RESPONSE_NO_DATA:
+       case PEX_MSG_UPDATE_RESPONSE_REFUSED:
                network_pex_recv_update_response(net, data, hdr->len,
                                              NULL, hdr->opcode);
                break;
@@ -1063,6 +1077,7 @@ global_pex_recv(void *msg, size_t msg_len, struct sockaddr_in6 *addr)
                fallthrough;
        case PEX_MSG_UPDATE_RESPONSE_DATA:
        case PEX_MSG_UPDATE_RESPONSE_NO_DATA:
+       case PEX_MSG_UPDATE_RESPONSE_REFUSED:
                network_pex_recv_update_response(net, data, hdr->len, addr, hdr->opcode);
                break;
        case PEX_MSG_ENDPOINT_PORT_NOTIFY:
diff --git a/ubus.c b/ubus.c
index 47fa743d3ac829babd72cc9397b4d8dc99983f62..d1852b5394229c0413d1b50176e9f6a08c51b0ad 100644 (file)
--- a/ubus.c
+++ b/ubus.c
@@ -71,8 +71,13 @@ __network_dump(struct blob_buf *buf, struct network *net)
                str = blobmsg_alloc_string_buffer(buf, "local_address", INET6_ADDRSTRLEN);
                inet_ntop(AF_INET6, &local->peer.local_addr.in6, str, INET6_ADDRSTRLEN);
                blobmsg_add_string_buffer(buf);
+       } else {
+               if (net->net_data_len)
+                       blobmsg_add_u8(buf, "no_local_host", true);
        }
 
+       if (net->update_refused)
+               blobmsg_add_u32(buf, "update_refused", net->update_refused);
 
        c = blobmsg_open_table(buf, "peers");
        vlist_for_each_element(&net->peers, peer, node) {