]> git.meshlink.io Git - meshlink/commitdiff
Add extra metering scenarios.
authorGuus Sliepen <guus@meshlink.io>
Mon, 20 Sep 2021 20:08:48 +0000 (22:08 +0200)
committerGuus Sliepen <guus@meshlink.io>
Mon, 20 Sep 2021 20:08:48 +0000 (22:08 +0200)
src/net_packet.c
src/sptps.c
src/sptps.h
test/Makefile.am
test/metering.c
test/netns_utils.c
test/netns_utils.h

index 4d47f0f3b7cbef9713a8944ec56270e22fd11c6b..acc90c97497668f00e491d724d801626e2648402 100644 (file)
@@ -29,6 +29,7 @@
 #include "netutl.h"
 #include "protocol.h"
 #include "route.h"
+#include "sptps.h"
 #include "utils.h"
 #include "xalloc.h"
 
@@ -37,6 +38,7 @@ int keylifetime = 0;
 static void send_udppacket(meshlink_handle_t *mesh, node_t *, vpn_packet_t *);
 
 #define MAX_SEQNO 1073741824
+#define PROBE_OVERHEAD (SPTPS_DATAGRAM_OVERHEAD + 40)
 
 /* mtuprobes == 1..30: initial discovery, send bursts with 1 second interval
    mtuprobes ==    31: sleep pinginterval seconds
@@ -142,7 +144,7 @@ static void send_mtu_probe_handler(event_loop_t *loop, void *data) {
 
                logger(mesh, MESHLINK_DEBUG, "Sending MTU probe length %d to %s", len, n->name);
 
-               n->out_meta += packet.len;
+               n->out_meta += packet.len + PROBE_OVERHEAD;
                send_udppacket(mesh, n, &packet);
        }
 
@@ -162,7 +164,7 @@ void send_mtu_probe(meshlink_handle_t *mesh, node_t *n) {
 }
 
 static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet, uint16_t len) {
-       n->in_meta += len;
+       n->in_meta += len + PROBE_OVERHEAD;
 
        if(len < 64) {
                logger(mesh, MESHLINK_WARNING, "Got too short MTU probe length %d from %s", packet->len, n->name);
@@ -182,7 +184,7 @@ static void mtu_probe_h(meshlink_handle_t *mesh, node_t *n, vpn_packet_t *packet
                bool udp_confirmed = n->status.udp_confirmed;
                n->status.udp_confirmed = true;
                logger(mesh, MESHLINK_DEBUG, "Sending MTU probe reply %d to %s", packet->len, n->name);
-               n->out_meta += packet->len;
+               n->out_meta += packet->len + PROBE_OVERHEAD;
                send_udppacket(mesh, n, packet);
                n->status.udp_confirmed = udp_confirmed;
        } else {
index fab2e9d9b8a87a05dba12cb00e0cacc910d5a419..d4a31e81812275d2253158156da42aff3f7885c8 100644 (file)
@@ -95,7 +95,7 @@ static void warning(sptps_t *s, const char *format, ...) {
 
 // Send a record (datagram version, accepts all record types, handles encryption and authentication).
 static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data, uint16_t len) {
-       char buffer[len + 21UL];
+       char buffer[len + SPTPS_DATAGRAM_OVERHEAD];
 
        // Create header with sequence number, length and record type
        uint32_t seqno = s->outseqno++;
@@ -108,7 +108,7 @@ static bool send_record_priv_datagram(sptps_t *s, uint8_t type, const void *data
        if(s->outstate) {
                // If first handshake has finished, encrypt and HMAC
                chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 4, len + 1, buffer + 4, NULL);
-               return s->send_data(s->handle, type, buffer, len + 21UL);
+               return s->send_data(s->handle, type, buffer, len + SPTPS_DATAGRAM_OVERHEAD);
        } else {
                // Otherwise send as plaintext
                return s->send_data(s->handle, type, buffer, len + 5UL);
@@ -120,7 +120,7 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_
                return send_record_priv_datagram(s, type, data, len);
        }
 
-       char buffer[len + 19UL];
+       char buffer[len + SPTPS_OVERHEAD];
 
        // Create header with sequence number, length and record type
        uint32_t seqno = s->outseqno++;
@@ -133,7 +133,7 @@ static bool send_record_priv(sptps_t *s, uint8_t type, const void *data, uint16_
        if(s->outstate) {
                // If first handshake has finished, encrypt and HMAC
                chacha_poly1305_encrypt(s->outcipher, seqno, buffer + 2, len + 1, buffer + 2, NULL);
-               return s->send_data(s->handle, type, buffer, len + 19UL);
+               return s->send_data(s->handle, type, buffer, len + SPTPS_OVERHEAD);
        } else {
                // Otherwise send as plaintext
                return s->send_data(s->handle, type, buffer, len + 3UL);
@@ -454,7 +454,7 @@ bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) {
                return error(s, EIO, "SPTPS state not ready to verify this datagram");
        }
 
-       if(len < 21) {
+       if(len < SPTPS_DATAGRAM_OVERHEAD) {
                return error(s, EIO, "Received short packet in sptps_verify_datagram");
        }
 
@@ -470,7 +470,7 @@ bool sptps_verify_datagram(sptps_t *s, const void *data, size_t len) {
 static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t len) {
        const char *data = vdata;
 
-       if(len < (s->instate ? 21 : 5)) {
+       if(len < (s->instate ? SPTPS_DATAGRAM_OVERHEAD : 5)) {
                return error(s, EIO, "Received short packet in sptps_receive_data_datagram");
        }
 
@@ -562,11 +562,11 @@ static bool sptps_receive_data_datagram(sptps_t *s, const void *vdata, size_t le
                        return error(s, EIO, "Application record received before handshake finished");
                }
 
-               if(!s->receive_record(s->handle, type, s->decrypted_buffer + 1, len - 21)) {
+               if(!s->receive_record(s->handle, type, s->decrypted_buffer + 1, len - SPTPS_DATAGRAM_OVERHEAD)) {
                        abort();
                }
        } else if(type == SPTPS_HANDSHAKE) {
-               if(!receive_handshake(s, s->decrypted_buffer + 1, len - 21)) {
+               if(!receive_handshake(s, s->decrypted_buffer + 1, len - SPTPS_DATAGRAM_OVERHEAD)) {
                        abort();
                }
        } else {
@@ -614,7 +614,7 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
                        s->reclen = ntohs(s->reclen);
 
                        // If we have the length bytes, ensure our buffer can hold the whole request.
-                       s->inbuf = realloc(s->inbuf, s->reclen + 19UL);
+                       s->inbuf = realloc(s->inbuf, s->reclen + SPTPS_OVERHEAD);
 
                        if(!s->inbuf) {
                                return error(s, errno, strerror(errno));
@@ -627,7 +627,7 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
                }
 
                // Read up to the end of the record.
-               size_t toread = s->reclen + (s->instate ? 19UL : 3UL) - s->buflen;
+               size_t toread = s->reclen + (s->instate ? SPTPS_OVERHEAD : 3UL) - s->buflen;
 
                if(toread > len) {
                        toread = len;
@@ -639,7 +639,7 @@ bool sptps_receive_data(sptps_t *s, const void *data, size_t len) {
                ptr += toread;
 
                // If we don't have a whole record, exit.
-               if(s->buflen < s->reclen + (s->instate ? 19UL : 3UL)) {
+               if(s->buflen < s->reclen + (s->instate ? SPTPS_OVERHEAD : 3UL)) {
                        return true;
                }
 
index ba6bcd57c0349e4c5f185c224be0646437222c74..6ed01186cfbcad6d43c4e3ae09b647f72e7d7da4 100644 (file)
 #define SPTPS_SIG 3           // Waiting for a SIGnature record
 #define SPTPS_ACK 4           // Waiting for an ACKnowledgement record
 
+// Packet header sizes
+#define SPTPS_OVERHEAD 19
+#define SPTPS_DATAGRAM_OVERHEAD 21
+
 typedef bool (*send_data_t)(void *handle, uint8_t type, const void *data, size_t len);
 typedef bool (*receive_record_t)(void *handle, uint8_t type, const void *data, uint16_t len);
 
index f5f4cdc5d034202b8516accd159d6ca9fb0aace3..94171596fb761c375017ef222ba90edb8f157f72 100644 (file)
@@ -21,6 +21,8 @@ TESTS = \
        import-export \
        invite-join \
        metering \
+       metering-relayed \
+       metering-tcponly \              
        meta-connections \
        sign-verify \
        storage-policy \
@@ -66,6 +68,8 @@ check_PROGRAMS = \
        import-export \
        invite-join \
        metering \
+       metering-relayed \
+       metering-tcponly \
        meta-connections \
        sign-verify \
        storage-policy \
@@ -149,6 +153,12 @@ invite_join_LDADD = $(top_builddir)/src/libmeshlink.la
 metering_SOURCES = metering.c netns_utils.c netns_utils.h utils.c utils.h
 metering_LDADD = $(top_builddir)/src/libmeshlink.la
 
+metering_relayed_SOURCES = metering-relayed.c netns_utils.c netns_utils.h utils.c utils.h
+metering_relayed_LDADD = $(top_builddir)/src/libmeshlink.la
+
+metering_tcponly_SOURCES = metering-tcponly.c netns_utils.c netns_utils.h utils.c utils.h
+metering_tcponly_LDADD = $(top_builddir)/src/libmeshlink.la
+
 meta_connections_SOURCES = meta-connections.c netns_utils.c netns_utils.h utils.c utils.h
 meta_connections_LDADD = $(top_builddir)/src/libmeshlink.la
 
index e302ead9ac63b502c1b67d806c5e66678230aef6..8ee7257c6a6201e9b082b849446bd296136da9e5 100644 (file)
@@ -90,7 +90,7 @@ int main(void) {
        init_sync_flag(&aio_done);
 
        // Set up relay, peer and NUT
-       peer_config_t *peers = setup_relay_peer_nut_indirect("metering");
+       peer_config_t *peers = setup_relay_peer_nut("metering");
 
        meshlink_set_node_status_cb(peers[2].mesh, nut_status_cb);
 
index 70fa3130df7b68672e03505b023be5d249999931..58c01ff5f60d9d24d1fd5aa8fb143c3f530fe914 100644 (file)
@@ -181,6 +181,20 @@ peer_config_t *setup_relay_peer_nut_indirect(const char *prefix) {
        return peers;
 }
 
+/// Make all nodes only be able to communicate via TCP
+void set_peers_tcponly(peer_config_t *peers, int npeers) {
+       for (int i = 0; i < npeers; i++) {
+               char *command = NULL;
+               assert(asprintf(&command,
+                                               "/bin/ip netns exec %1$s iptables -A INPUT -p udp -j DROP;"
+                                               "/bin/ip netns exec %1$s iptables -A OUTPUT -p udp -j DROP;",
+                                               peers[i].netns_name));
+               assert(command);
+               assert(system(command) == 0);
+               free(command);
+       }
+}
+
 void close_relay_peer_nut(peer_config_t *peers) {
        close_peers(peers, 3);
 }
index 5f84f9c4bc2d2b6104dd3fa8942bab0eed852a3f..0c0c44819bda6b31221c3b2e81ef4e6e0748323e 100644 (file)
@@ -13,6 +13,7 @@ typedef struct peer_config {
 extern void change_peer_ip(peer_config_t *peer);
 extern peer_config_t *setup_relay_peer_nut(const char *prefix);
 extern peer_config_t *setup_relay_peer_nut_indirect(const char *prefix);
+extern void set_peers_tcponly(peer_config_t *peers, int npeers);
 extern void close_relay_peer_nut(peer_config_t *peers);
 
 #endif