mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
Included features:
* use bitops.h API when possible * send netlink notification in case of client float event * implement support for asymmetric peer IDs * consolidate memory allocations during crypto operations * add netlink notification check in selftests * add FW mark check in selftest -----BEGIN PGP SIGNATURE----- iJEEABYIADkWIQQKU153ubb5unbkl6Gx/ZpNW1HNdwUCabkqjRsUgAAAAAAEAA5t YW51MiwyLjUrMS4xMSwyLDIACgkQsf2aTVtRzXdlaAEA4fQA41/tbgsciMSf7aqT lEAbZF/6DnsFZiTmuUfqPvQA/3+R0uiJlUTB3NGhhXXXikP4Yj61lWMDjw//lvYJ 74IG =elM6 -----END PGP SIGNATURE----- Merge tag 'ovpn-net-next-20260317' of https://github.com/OpenVPN/ovpn-net-next Antonio Quartulli says: ==================== Included features: * use bitops.h API when possible * send netlink notification in case of client float event * implement support for asymmetric peer IDs * consolidate memory allocations during crypto operations * add netlink notification check in selftests * add FW mark check in selftest * tag 'ovpn-net-next-20260317' of https://github.com/OpenVPN/ovpn-net-next: ovpn: consolidate crypto allocations in one chunk selftests: ovpn: add test for the FW mark feature selftests: ovpn: check asymmetric peer-id ovpn: add support for asymmetric peer IDs selftests: ovpn: add notification parsing and matching ovpn: notify userspace on client float event ovpn: pktid: use bitops.h API ovpn: use correct array size to parse nested attributes in ovpn_nl_key_swap_doit selftests: ovpn: allow compiling ovpn-cli.c with mbedtls3 ==================== Link: https://patch.msgid.link/20260317104023.192548-1-antonio@openvpn.net Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
commit
0c45064487
|
|
@ -43,7 +43,8 @@ attribute-sets:
|
|||
type: u32
|
||||
doc: >-
|
||||
The unique ID of the peer in the device context. To be used to
|
||||
identify peers during operations for a specific device
|
||||
identify peers during operations for a specific device.
|
||||
Also used to match packets received from this peer.
|
||||
checks:
|
||||
max: 0xFFFFFF
|
||||
-
|
||||
|
|
@ -160,6 +161,16 @@ attribute-sets:
|
|||
name: link-tx-packets
|
||||
type: uint
|
||||
doc: Number of packets transmitted at the transport level
|
||||
-
|
||||
name: tx-id
|
||||
type: u32
|
||||
doc: >-
|
||||
The ID value used when transmitting packets to this peer. This
|
||||
way outgoing packets can have a different ID than incoming ones.
|
||||
Useful in multipeer-to-multipeer connections, where each peer
|
||||
will advertise the tx-id to be used on the link.
|
||||
checks:
|
||||
max: 0xFFFFFF
|
||||
-
|
||||
name: peer-new-input
|
||||
subset-of: peer
|
||||
|
|
@ -188,6 +199,8 @@ attribute-sets:
|
|||
name: keepalive-interval
|
||||
-
|
||||
name: keepalive-timeout
|
||||
-
|
||||
name: tx-id
|
||||
-
|
||||
name: peer-set-input
|
||||
subset-of: peer
|
||||
|
|
@ -214,6 +227,8 @@ attribute-sets:
|
|||
name: keepalive-interval
|
||||
-
|
||||
name: keepalive-timeout
|
||||
-
|
||||
name: tx-id
|
||||
-
|
||||
name: peer-del-input
|
||||
subset-of: peer
|
||||
|
|
@ -502,6 +517,12 @@ operations:
|
|||
- ifindex
|
||||
- keyconf
|
||||
|
||||
-
|
||||
name: peer-float-ntf
|
||||
doc: Notification about a peer floating (changing its remote UDP endpoint)
|
||||
notify: peer-get
|
||||
mcgrp: peers
|
||||
|
||||
mcast-groups:
|
||||
list:
|
||||
-
|
||||
|
|
|
|||
|
|
@ -36,6 +36,104 @@ static int ovpn_aead_encap_overhead(const struct ovpn_crypto_key_slot *ks)
|
|||
crypto_aead_authsize(ks->encrypt); /* Auth Tag */
|
||||
}
|
||||
|
||||
/**
|
||||
* ovpn_aead_crypto_tmp_size - compute the size of a temporary object containing
|
||||
* an AEAD request structure with extra space for SG
|
||||
* and IV.
|
||||
* @tfm: the AEAD cipher handle
|
||||
* @nfrags: the number of fragments in the skb
|
||||
*
|
||||
* This function calculates the size of a contiguous memory block that includes
|
||||
* the initialization vector (IV), the AEAD request, and an array of scatterlist
|
||||
* entries. For alignment considerations, the IV is placed first, followed by
|
||||
* the request, and then the scatterlist.
|
||||
* Additional alignment is applied according to the requirements of the
|
||||
* underlying structures.
|
||||
*
|
||||
* Return: the size of the temporary memory that needs to be allocated
|
||||
*/
|
||||
static unsigned int ovpn_aead_crypto_tmp_size(struct crypto_aead *tfm,
|
||||
const unsigned int nfrags)
|
||||
{
|
||||
unsigned int len = OVPN_NONCE_SIZE;
|
||||
|
||||
DEBUG_NET_WARN_ON_ONCE(crypto_aead_ivsize(tfm) != OVPN_NONCE_SIZE);
|
||||
|
||||
/* min size for a buffer of ivsize, aligned to alignmask */
|
||||
len += crypto_aead_alignmask(tfm) & ~(crypto_tfm_ctx_alignment() - 1);
|
||||
/* round up to the next multiple of the crypto ctx alignment */
|
||||
len = ALIGN(len, crypto_tfm_ctx_alignment());
|
||||
|
||||
/* reserve space for the AEAD request */
|
||||
len += sizeof(struct aead_request) + crypto_aead_reqsize(tfm);
|
||||
/* round up to the next multiple of the scatterlist alignment */
|
||||
len = ALIGN(len, __alignof__(struct scatterlist));
|
||||
|
||||
/* add enough space for nfrags + 2 scatterlist entries */
|
||||
len += array_size(sizeof(struct scatterlist), nfrags + 2);
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* ovpn_aead_crypto_tmp_iv - retrieve the pointer to the IV within a temporary
|
||||
* buffer allocated using ovpn_aead_crypto_tmp_size
|
||||
* @aead: the AEAD cipher handle
|
||||
* @tmp: a pointer to the beginning of the temporary buffer
|
||||
*
|
||||
* This function retrieves a pointer to the initialization vector (IV) in the
|
||||
* temporary buffer. If the AEAD cipher specifies an IV size, the pointer is
|
||||
* adjusted using the AEAD's alignment mask to ensure proper alignment.
|
||||
*
|
||||
* Returns: a pointer to the IV within the temporary buffer
|
||||
*/
|
||||
static u8 *ovpn_aead_crypto_tmp_iv(struct crypto_aead *aead, void *tmp)
|
||||
{
|
||||
return likely(crypto_aead_ivsize(aead)) ?
|
||||
PTR_ALIGN((u8 *)tmp, crypto_aead_alignmask(aead) + 1) :
|
||||
tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* ovpn_aead_crypto_tmp_req - retrieve the pointer to the AEAD request structure
|
||||
* within a temporary buffer allocated using
|
||||
* ovpn_aead_crypto_tmp_size
|
||||
* @aead: the AEAD cipher handle
|
||||
* @iv: a pointer to the initialization vector in the temporary buffer
|
||||
*
|
||||
* This function computes the location of the AEAD request structure that
|
||||
* immediately follows the IV in the temporary buffer and it ensures the request
|
||||
* is aligned to the crypto transform context alignment.
|
||||
*
|
||||
* Returns: a pointer to the AEAD request structure
|
||||
*/
|
||||
static struct aead_request *ovpn_aead_crypto_tmp_req(struct crypto_aead *aead,
|
||||
const u8 *iv)
|
||||
{
|
||||
return (void *)PTR_ALIGN(iv + crypto_aead_ivsize(aead),
|
||||
crypto_tfm_ctx_alignment());
|
||||
}
|
||||
|
||||
/**
|
||||
* ovpn_aead_crypto_req_sg - locate the scatterlist following the AEAD request
|
||||
* within a temporary buffer allocated using
|
||||
* ovpn_aead_crypto_tmp_size
|
||||
* @aead: the AEAD cipher handle
|
||||
* @req: a pointer to the AEAD request structure in the temporary buffer
|
||||
*
|
||||
* This function computes the starting address of the scatterlist that is
|
||||
* allocated immediately after the AEAD request structure. It aligns the pointer
|
||||
* based on the alignment requirements of the scatterlist structure.
|
||||
*
|
||||
* Returns: a pointer to the scatterlist
|
||||
*/
|
||||
static struct scatterlist *ovpn_aead_crypto_req_sg(struct crypto_aead *aead,
|
||||
struct aead_request *req)
|
||||
{
|
||||
return (void *)ALIGN((unsigned long)(req + 1) +
|
||||
crypto_aead_reqsize(aead),
|
||||
__alignof__(struct scatterlist));
|
||||
}
|
||||
|
||||
int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
|
|
@ -45,6 +143,7 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
struct scatterlist *sg;
|
||||
int nfrags, ret;
|
||||
u32 pktid, op;
|
||||
void *tmp;
|
||||
u8 *iv;
|
||||
|
||||
ovpn_skb_cb(skb)->peer = peer;
|
||||
|
|
@ -71,13 +170,17 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
if (unlikely(nfrags + 2 > (MAX_SKB_FRAGS + 2)))
|
||||
return -ENOSPC;
|
||||
|
||||
/* sg may be required by async crypto */
|
||||
ovpn_skb_cb(skb)->sg = kmalloc(sizeof(*ovpn_skb_cb(skb)->sg) *
|
||||
(nfrags + 2), GFP_ATOMIC);
|
||||
if (unlikely(!ovpn_skb_cb(skb)->sg))
|
||||
/* allocate temporary memory for iv, sg and req */
|
||||
tmp = kmalloc(ovpn_aead_crypto_tmp_size(ks->encrypt, nfrags),
|
||||
GFP_ATOMIC);
|
||||
if (unlikely(!tmp))
|
||||
return -ENOMEM;
|
||||
|
||||
sg = ovpn_skb_cb(skb)->sg;
|
||||
ovpn_skb_cb(skb)->crypto_tmp = tmp;
|
||||
|
||||
iv = ovpn_aead_crypto_tmp_iv(ks->encrypt, tmp);
|
||||
req = ovpn_aead_crypto_tmp_req(ks->encrypt, iv);
|
||||
sg = ovpn_aead_crypto_req_sg(ks->encrypt, req);
|
||||
|
||||
/* sg table:
|
||||
* 0: op, wire nonce (AD, len=OVPN_OP_SIZE_V2+OVPN_NONCE_WIRE_SIZE),
|
||||
|
|
@ -105,13 +208,6 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
||||
/* iv may be required by async crypto */
|
||||
ovpn_skb_cb(skb)->iv = kmalloc(OVPN_NONCE_SIZE, GFP_ATOMIC);
|
||||
if (unlikely(!ovpn_skb_cb(skb)->iv))
|
||||
return -ENOMEM;
|
||||
|
||||
iv = ovpn_skb_cb(skb)->iv;
|
||||
|
||||
/* concat 4 bytes packet id and 8 bytes nonce tail into 12 bytes
|
||||
* nonce
|
||||
*/
|
||||
|
|
@ -122,7 +218,7 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
memcpy(skb->data, iv, OVPN_NONCE_WIRE_SIZE);
|
||||
|
||||
/* add packet op as head of additional data */
|
||||
op = ovpn_opcode_compose(OVPN_DATA_V2, ks->key_id, peer->id);
|
||||
op = ovpn_opcode_compose(OVPN_DATA_V2, ks->key_id, peer->tx_id);
|
||||
__skb_push(skb, OVPN_OPCODE_SIZE);
|
||||
BUILD_BUG_ON(sizeof(op) != OVPN_OPCODE_SIZE);
|
||||
*((__force __be32 *)skb->data) = htonl(op);
|
||||
|
|
@ -130,12 +226,6 @@ int ovpn_aead_encrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
/* AEAD Additional data */
|
||||
sg_set_buf(sg, skb->data, OVPN_AAD_SIZE);
|
||||
|
||||
req = aead_request_alloc(ks->encrypt, GFP_ATOMIC);
|
||||
if (unlikely(!req))
|
||||
return -ENOMEM;
|
||||
|
||||
ovpn_skb_cb(skb)->req = req;
|
||||
|
||||
/* setup async crypto operation */
|
||||
aead_request_set_tfm(req, ks->encrypt);
|
||||
aead_request_set_callback(req, 0, ovpn_encrypt_post, skb);
|
||||
|
|
@ -156,6 +246,7 @@ int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
struct aead_request *req;
|
||||
struct sk_buff *trailer;
|
||||
struct scatterlist *sg;
|
||||
void *tmp;
|
||||
u8 *iv;
|
||||
|
||||
payload_offset = OVPN_AAD_SIZE + tag_size;
|
||||
|
|
@ -184,13 +275,17 @@ int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
if (unlikely(nfrags + 2 > (MAX_SKB_FRAGS + 2)))
|
||||
return -ENOSPC;
|
||||
|
||||
/* sg may be required by async crypto */
|
||||
ovpn_skb_cb(skb)->sg = kmalloc(sizeof(*ovpn_skb_cb(skb)->sg) *
|
||||
(nfrags + 2), GFP_ATOMIC);
|
||||
if (unlikely(!ovpn_skb_cb(skb)->sg))
|
||||
/* allocate temporary memory for iv, sg and req */
|
||||
tmp = kmalloc(ovpn_aead_crypto_tmp_size(ks->decrypt, nfrags),
|
||||
GFP_ATOMIC);
|
||||
if (unlikely(!tmp))
|
||||
return -ENOMEM;
|
||||
|
||||
sg = ovpn_skb_cb(skb)->sg;
|
||||
ovpn_skb_cb(skb)->crypto_tmp = tmp;
|
||||
|
||||
iv = ovpn_aead_crypto_tmp_iv(ks->decrypt, tmp);
|
||||
req = ovpn_aead_crypto_tmp_req(ks->decrypt, iv);
|
||||
sg = ovpn_aead_crypto_req_sg(ks->decrypt, req);
|
||||
|
||||
/* sg table:
|
||||
* 0: op, wire nonce (AD, len=OVPN_OPCODE_SIZE+OVPN_NONCE_WIRE_SIZE),
|
||||
|
|
@ -213,24 +308,11 @@ int ovpn_aead_decrypt(struct ovpn_peer *peer, struct ovpn_crypto_key_slot *ks,
|
|||
/* append auth_tag onto scatterlist */
|
||||
sg_set_buf(sg + ret + 1, skb->data + OVPN_AAD_SIZE, tag_size);
|
||||
|
||||
/* iv may be required by async crypto */
|
||||
ovpn_skb_cb(skb)->iv = kmalloc(OVPN_NONCE_SIZE, GFP_ATOMIC);
|
||||
if (unlikely(!ovpn_skb_cb(skb)->iv))
|
||||
return -ENOMEM;
|
||||
|
||||
iv = ovpn_skb_cb(skb)->iv;
|
||||
|
||||
/* copy nonce into IV buffer */
|
||||
memcpy(iv, skb->data + OVPN_OPCODE_SIZE, OVPN_NONCE_WIRE_SIZE);
|
||||
memcpy(iv + OVPN_NONCE_WIRE_SIZE, ks->nonce_tail_recv,
|
||||
OVPN_NONCE_TAIL_SIZE);
|
||||
|
||||
req = aead_request_alloc(ks->decrypt, GFP_ATOMIC);
|
||||
if (unlikely(!req))
|
||||
return -ENOMEM;
|
||||
|
||||
ovpn_skb_cb(skb)->req = req;
|
||||
|
||||
/* setup async crypto operation */
|
||||
aead_request_set_tfm(req, ks->decrypt);
|
||||
aead_request_set_callback(req, 0, ovpn_decrypt_post, skb);
|
||||
|
|
@ -273,7 +355,11 @@ static struct crypto_aead *ovpn_aead_init(const char *title,
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* basic AEAD assumption */
|
||||
/* basic AEAD assumption
|
||||
* all current algorithms use OVPN_NONCE_SIZE.
|
||||
* ovpn_aead_crypto_tmp_size and ovpn_aead_encrypt/decrypt
|
||||
* expect this.
|
||||
*/
|
||||
if (crypto_aead_ivsize(aead) != OVPN_NONCE_SIZE) {
|
||||
pr_err("%s IV size must be %d\n", title, OVPN_NONCE_SIZE);
|
||||
ret = -EINVAL;
|
||||
|
|
|
|||
|
|
@ -119,9 +119,7 @@ void ovpn_decrypt_post(void *data, int ret)
|
|||
peer = ovpn_skb_cb(skb)->peer;
|
||||
|
||||
/* crypto is done, cleanup skb CB and its members */
|
||||
kfree(ovpn_skb_cb(skb)->iv);
|
||||
kfree(ovpn_skb_cb(skb)->sg);
|
||||
aead_request_free(ovpn_skb_cb(skb)->req);
|
||||
kfree(ovpn_skb_cb(skb)->crypto_tmp);
|
||||
|
||||
if (unlikely(ret < 0))
|
||||
goto drop;
|
||||
|
|
@ -248,9 +246,7 @@ void ovpn_encrypt_post(void *data, int ret)
|
|||
peer = ovpn_skb_cb(skb)->peer;
|
||||
|
||||
/* crypto is done, cleanup skb CB and its members */
|
||||
kfree(ovpn_skb_cb(skb)->iv);
|
||||
kfree(ovpn_skb_cb(skb)->sg);
|
||||
aead_request_free(ovpn_skb_cb(skb)->req);
|
||||
kfree(ovpn_skb_cb(skb)->crypto_tmp);
|
||||
|
||||
if (unlikely(ret == -ERANGE)) {
|
||||
/* we ran out of IVs and we must kill the key as it can't be
|
||||
|
|
|
|||
|
|
@ -16,6 +16,10 @@ static const struct netlink_range_validation ovpn_a_peer_id_range = {
|
|||
.max = 16777215ULL,
|
||||
};
|
||||
|
||||
static const struct netlink_range_validation ovpn_a_peer_tx_id_range = {
|
||||
.max = 16777215ULL,
|
||||
};
|
||||
|
||||
static const struct netlink_range_validation ovpn_a_keyconf_peer_id_range = {
|
||||
.max = 16777215ULL,
|
||||
};
|
||||
|
|
@ -51,7 +55,7 @@ const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1] = {
|
|||
[OVPN_A_KEYDIR_NONCE_TAIL] = NLA_POLICY_EXACT_LEN(OVPN_NONCE_TAIL_SIZE),
|
||||
};
|
||||
|
||||
const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1] = {
|
||||
const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_TX_ID + 1] = {
|
||||
[OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range),
|
||||
[OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, },
|
||||
[OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16),
|
||||
|
|
@ -75,13 +79,14 @@ const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1] = {
|
|||
[OVPN_A_PEER_LINK_TX_BYTES] = { .type = NLA_UINT, },
|
||||
[OVPN_A_PEER_LINK_RX_PACKETS] = { .type = NLA_UINT, },
|
||||
[OVPN_A_PEER_LINK_TX_PACKETS] = { .type = NLA_UINT, },
|
||||
[OVPN_A_PEER_TX_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_tx_id_range),
|
||||
};
|
||||
|
||||
const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1] = {
|
||||
[OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range),
|
||||
};
|
||||
|
||||
const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1] = {
|
||||
const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = {
|
||||
[OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range),
|
||||
[OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, },
|
||||
[OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16),
|
||||
|
|
@ -94,9 +99,10 @@ const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIME
|
|||
[OVPN_A_PEER_LOCAL_IPV6] = NLA_POLICY_EXACT_LEN(16),
|
||||
[OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, },
|
||||
[OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, },
|
||||
[OVPN_A_PEER_TX_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_tx_id_range),
|
||||
};
|
||||
|
||||
const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1] = {
|
||||
const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_TX_ID + 1] = {
|
||||
[OVPN_A_PEER_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_id_range),
|
||||
[OVPN_A_PEER_REMOTE_IPV4] = { .type = NLA_BE32, },
|
||||
[OVPN_A_PEER_REMOTE_IPV6] = NLA_POLICY_EXACT_LEN(16),
|
||||
|
|
@ -108,6 +114,7 @@ const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIME
|
|||
[OVPN_A_PEER_LOCAL_IPV6] = NLA_POLICY_EXACT_LEN(16),
|
||||
[OVPN_A_PEER_KEEPALIVE_INTERVAL] = { .type = NLA_U32, },
|
||||
[OVPN_A_PEER_KEEPALIVE_TIMEOUT] = { .type = NLA_U32, },
|
||||
[OVPN_A_PEER_TX_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &ovpn_a_peer_tx_id_range),
|
||||
};
|
||||
|
||||
/* OVPN_CMD_PEER_NEW - do */
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ extern const struct nla_policy ovpn_keyconf_del_input_nl_policy[OVPN_A_KEYCONF_S
|
|||
extern const struct nla_policy ovpn_keyconf_get_nl_policy[OVPN_A_KEYCONF_CIPHER_ALG + 1];
|
||||
extern const struct nla_policy ovpn_keyconf_swap_input_nl_policy[OVPN_A_KEYCONF_PEER_ID + 1];
|
||||
extern const struct nla_policy ovpn_keydir_nl_policy[OVPN_A_KEYDIR_NONCE_TAIL + 1];
|
||||
extern const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_LINK_TX_PACKETS + 1];
|
||||
extern const struct nla_policy ovpn_peer_nl_policy[OVPN_A_PEER_TX_ID + 1];
|
||||
extern const struct nla_policy ovpn_peer_del_input_nl_policy[OVPN_A_PEER_ID + 1];
|
||||
extern const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1];
|
||||
extern const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_KEEPALIVE_TIMEOUT + 1];
|
||||
extern const struct nla_policy ovpn_peer_new_input_nl_policy[OVPN_A_PEER_TX_ID + 1];
|
||||
extern const struct nla_policy ovpn_peer_set_input_nl_policy[OVPN_A_PEER_TX_ID + 1];
|
||||
|
||||
int ovpn_nl_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
|
||||
struct genl_info *info);
|
||||
|
|
|
|||
|
|
@ -305,6 +305,12 @@ static int ovpn_nl_peer_modify(struct ovpn_peer *peer, struct genl_info *info,
|
|||
dst_cache_reset(&peer->dst_cache);
|
||||
}
|
||||
|
||||
/* In a multipeer-to-multipeer setup we may have asymmetric peer IDs,
|
||||
* that is peer->id might be different from peer->tx_id.
|
||||
*/
|
||||
if (attrs[OVPN_A_PEER_TX_ID])
|
||||
peer->tx_id = nla_get_u32(attrs[OVPN_A_PEER_TX_ID]);
|
||||
|
||||
if (attrs[OVPN_A_PEER_VPN_IPV4]) {
|
||||
rehash = true;
|
||||
peer->vpn_addrs.ipv4.s_addr =
|
||||
|
|
@ -326,8 +332,8 @@ static int ovpn_nl_peer_modify(struct ovpn_peer *peer, struct genl_info *info,
|
|||
}
|
||||
|
||||
netdev_dbg(peer->ovpn->dev,
|
||||
"modify peer id=%u endpoint=%pIScp VPN-IPv4=%pI4 VPN-IPv6=%pI6c\n",
|
||||
peer->id, &ss,
|
||||
"modify peer id=%u tx_id=%u endpoint=%pIScp VPN-IPv4=%pI4 VPN-IPv6=%pI6c\n",
|
||||
peer->id, peer->tx_id, &ss,
|
||||
&peer->vpn_addrs.ipv4.s_addr, &peer->vpn_addrs.ipv6);
|
||||
|
||||
spin_unlock_bh(&peer->lock);
|
||||
|
|
@ -373,6 +379,7 @@ int ovpn_nl_peer_new_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
}
|
||||
|
||||
peer_id = nla_get_u32(attrs[OVPN_A_PEER_ID]);
|
||||
|
||||
peer = ovpn_peer_new(ovpn, peer_id);
|
||||
if (IS_ERR(peer)) {
|
||||
NL_SET_ERR_MSG_FMT_MOD(info->extack,
|
||||
|
|
@ -572,6 +579,9 @@ static int ovpn_nl_send_peer(struct sk_buff *skb, const struct genl_info *info,
|
|||
if (nla_put_u32(skb, OVPN_A_PEER_ID, peer->id))
|
||||
goto err;
|
||||
|
||||
if (nla_put_u32(skb, OVPN_A_PEER_TX_ID, peer->tx_id))
|
||||
goto err;
|
||||
|
||||
if (peer->vpn_addrs.ipv4.s_addr != htonl(INADDR_ANY))
|
||||
if (nla_put_in_addr(skb, OVPN_A_PEER_VPN_IPV4,
|
||||
peer->vpn_addrs.ipv4.s_addr))
|
||||
|
|
@ -1061,8 +1071,8 @@ int ovpn_nl_key_get_doit(struct sk_buff *skb, struct genl_info *info)
|
|||
|
||||
int ovpn_nl_key_swap_doit(struct sk_buff *skb, struct genl_info *info)
|
||||
{
|
||||
struct nlattr *attrs[OVPN_A_KEYCONF_MAX + 1];
|
||||
struct ovpn_priv *ovpn = info->user_ptr[0];
|
||||
struct nlattr *attrs[OVPN_A_PEER_MAX + 1];
|
||||
struct ovpn_peer *peer;
|
||||
u32 peer_id;
|
||||
int ret;
|
||||
|
|
@ -1203,6 +1213,88 @@ int ovpn_nl_peer_del_notify(struct ovpn_peer *peer)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ovpn_nl_peer_float_notify - notify userspace about peer floating
|
||||
* @peer: the floated peer
|
||||
* @ss: sockaddr representing the new remote endpoint
|
||||
*
|
||||
* Return: 0 on success or a negative error code otherwise
|
||||
*/
|
||||
int ovpn_nl_peer_float_notify(struct ovpn_peer *peer,
|
||||
const struct sockaddr_storage *ss)
|
||||
{
|
||||
struct ovpn_socket *sock;
|
||||
struct sockaddr_in6 *sa6;
|
||||
struct sockaddr_in *sa;
|
||||
struct sk_buff *msg;
|
||||
struct nlattr *attr;
|
||||
int ret = -EMSGSIZE;
|
||||
void *hdr;
|
||||
|
||||
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
||||
if (!msg)
|
||||
return -ENOMEM;
|
||||
|
||||
hdr = genlmsg_put(msg, 0, 0, &ovpn_nl_family, 0,
|
||||
OVPN_CMD_PEER_FLOAT_NTF);
|
||||
if (!hdr) {
|
||||
ret = -ENOBUFS;
|
||||
goto err_free_msg;
|
||||
}
|
||||
|
||||
if (nla_put_u32(msg, OVPN_A_IFINDEX, peer->ovpn->dev->ifindex))
|
||||
goto err_cancel_msg;
|
||||
|
||||
attr = nla_nest_start(msg, OVPN_A_PEER);
|
||||
if (!attr)
|
||||
goto err_cancel_msg;
|
||||
|
||||
if (nla_put_u32(msg, OVPN_A_PEER_ID, peer->id))
|
||||
goto err_cancel_msg;
|
||||
|
||||
if (ss->ss_family == AF_INET) {
|
||||
sa = (struct sockaddr_in *)ss;
|
||||
if (nla_put_in_addr(msg, OVPN_A_PEER_REMOTE_IPV4,
|
||||
sa->sin_addr.s_addr) ||
|
||||
nla_put_net16(msg, OVPN_A_PEER_REMOTE_PORT, sa->sin_port))
|
||||
goto err_cancel_msg;
|
||||
} else if (ss->ss_family == AF_INET6) {
|
||||
sa6 = (struct sockaddr_in6 *)ss;
|
||||
if (nla_put_in6_addr(msg, OVPN_A_PEER_REMOTE_IPV6,
|
||||
&sa6->sin6_addr) ||
|
||||
nla_put_u32(msg, OVPN_A_PEER_REMOTE_IPV6_SCOPE_ID,
|
||||
sa6->sin6_scope_id) ||
|
||||
nla_put_net16(msg, OVPN_A_PEER_REMOTE_PORT, sa6->sin6_port))
|
||||
goto err_cancel_msg;
|
||||
} else {
|
||||
ret = -EAFNOSUPPORT;
|
||||
goto err_cancel_msg;
|
||||
}
|
||||
|
||||
nla_nest_end(msg, attr);
|
||||
genlmsg_end(msg, hdr);
|
||||
|
||||
rcu_read_lock();
|
||||
sock = rcu_dereference(peer->sock);
|
||||
if (!sock) {
|
||||
ret = -EINVAL;
|
||||
goto err_unlock;
|
||||
}
|
||||
genlmsg_multicast_netns(&ovpn_nl_family, sock_net(sock->sk), msg,
|
||||
0, OVPN_NLGRP_PEERS, GFP_ATOMIC);
|
||||
rcu_read_unlock();
|
||||
|
||||
return 0;
|
||||
|
||||
err_unlock:
|
||||
rcu_read_unlock();
|
||||
err_cancel_msg:
|
||||
genlmsg_cancel(msg, hdr);
|
||||
err_free_msg:
|
||||
nlmsg_free(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ovpn_nl_key_swap_notify - notify userspace peer's key must be renewed
|
||||
* @peer: the peer whose key needs to be renewed
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ int ovpn_nl_register(void);
|
|||
void ovpn_nl_unregister(void);
|
||||
|
||||
int ovpn_nl_peer_del_notify(struct ovpn_peer *peer);
|
||||
int ovpn_nl_peer_float_notify(struct ovpn_peer *peer,
|
||||
const struct sockaddr_storage *ss);
|
||||
int ovpn_nl_key_swap_notify(struct ovpn_peer *peer, u8 key_id);
|
||||
|
||||
#endif /* _NET_OVPN_NETLINK_H_ */
|
||||
|
|
|
|||
|
|
@ -99,7 +99,11 @@ struct ovpn_peer *ovpn_peer_new(struct ovpn_priv *ovpn, u32 id)
|
|||
if (!peer)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
/* in the default case TX and RX IDs are the same.
|
||||
* the user may set a different TX ID via netlink
|
||||
*/
|
||||
peer->id = id;
|
||||
peer->tx_id = id;
|
||||
peer->ovpn = ovpn;
|
||||
|
||||
peer->vpn_addrs.ipv4.s_addr = htonl(INADDR_ANY);
|
||||
|
|
@ -287,6 +291,8 @@ void ovpn_peer_endpoints_update(struct ovpn_peer *peer, struct sk_buff *skb)
|
|||
|
||||
spin_unlock_bh(&peer->lock);
|
||||
|
||||
ovpn_nl_peer_float_notify(peer, &ss);
|
||||
|
||||
/* rehashing is required only in MP mode as P2P has one peer
|
||||
* only and thus there is no hashtable
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@
|
|||
* struct ovpn_peer - the main remote peer object
|
||||
* @ovpn: main openvpn instance this peer belongs to
|
||||
* @dev_tracker: reference tracker for associated dev
|
||||
* @id: unique identifier
|
||||
* @id: unique identifier, used to match incoming packets
|
||||
* @tx_id: identifier to be used in TX packets
|
||||
* @vpn_addrs: IP addresses assigned over the tunnel
|
||||
* @vpn_addrs.ipv4: IPv4 assigned to peer on the tunnel
|
||||
* @vpn_addrs.ipv6: IPv6 assigned to peer on the tunnel
|
||||
|
|
@ -64,6 +65,7 @@ struct ovpn_peer {
|
|||
struct ovpn_priv *ovpn;
|
||||
netdevice_tracker dev_tracker;
|
||||
u32 id;
|
||||
u32 tx_id;
|
||||
struct {
|
||||
struct in_addr ipv4;
|
||||
struct in6_addr ipv6;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ int ovpn_pktid_recv(struct ovpn_pktid_recv *pr, u32 pkt_id, u32 pkt_time)
|
|||
if (likely(pkt_id == pr->id + 1)) {
|
||||
/* well-formed ID sequence (incremented by 1) */
|
||||
pr->base = REPLAY_INDEX(pr->base, -1);
|
||||
pr->history[pr->base / 8] |= (1 << (pr->base % 8));
|
||||
__set_bit(pr->base, pr->history);
|
||||
if (pr->extent < REPLAY_WINDOW_SIZE)
|
||||
++pr->extent;
|
||||
pr->id = pkt_id;
|
||||
|
|
@ -77,14 +77,14 @@ int ovpn_pktid_recv(struct ovpn_pktid_recv *pr, u32 pkt_id, u32 pkt_time)
|
|||
unsigned int i;
|
||||
|
||||
pr->base = REPLAY_INDEX(pr->base, -delta);
|
||||
pr->history[pr->base / 8] |= (1 << (pr->base % 8));
|
||||
__set_bit(pr->base, pr->history);
|
||||
pr->extent += delta;
|
||||
if (pr->extent > REPLAY_WINDOW_SIZE)
|
||||
pr->extent = REPLAY_WINDOW_SIZE;
|
||||
for (i = 1; i < delta; ++i) {
|
||||
unsigned int newb = REPLAY_INDEX(pr->base, i);
|
||||
|
||||
pr->history[newb / 8] &= ~BIT(newb % 8);
|
||||
__clear_bit(newb, pr->history);
|
||||
}
|
||||
} else {
|
||||
pr->base = 0;
|
||||
|
|
@ -103,14 +103,11 @@ int ovpn_pktid_recv(struct ovpn_pktid_recv *pr, u32 pkt_id, u32 pkt_time)
|
|||
if (pkt_id > pr->id_floor) {
|
||||
const unsigned int ri = REPLAY_INDEX(pr->base,
|
||||
delta);
|
||||
u8 *p = &pr->history[ri / 8];
|
||||
const u8 mask = (1 << (ri % 8));
|
||||
|
||||
if (*p & mask) {
|
||||
if (__test_and_set_bit(ri, pr->history)) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
*p |= mask;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ struct ovpn_pktid_xmit {
|
|||
*/
|
||||
struct ovpn_pktid_recv {
|
||||
/* "sliding window" bitmask of recent packet IDs received */
|
||||
u8 history[REPLAY_WINDOW_BYTES];
|
||||
DECLARE_BITMAP(history, REPLAY_WINDOW_SIZE);
|
||||
/* bit position of deque base in history */
|
||||
unsigned int base;
|
||||
/* extent (in bits) of deque in history */
|
||||
|
|
|
|||
|
|
@ -18,12 +18,19 @@
|
|||
#include <linux/socket.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
/**
|
||||
* struct ovpn_cb - ovpn skb control block
|
||||
* @peer: the peer this skb was received from/sent to
|
||||
* @ks: the crypto key slot used to encrypt/decrypt this skb
|
||||
* @crypto_tmp: pointer to temporary memory used for crypto operations
|
||||
* containing the IV, the scatter gather list and the aead request
|
||||
* @payload_offset: offset in the skb where the payload starts
|
||||
* @nosignal: whether this skb should be sent with the MSG_NOSIGNAL flag (TCP)
|
||||
*/
|
||||
struct ovpn_cb {
|
||||
struct ovpn_peer *peer;
|
||||
struct ovpn_crypto_key_slot *ks;
|
||||
struct aead_request *req;
|
||||
struct scatterlist *sg;
|
||||
u8 *iv;
|
||||
void *crypto_tmp;
|
||||
unsigned int payload_offset;
|
||||
bool nosignal;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ enum {
|
|||
OVPN_A_PEER_LINK_TX_BYTES,
|
||||
OVPN_A_PEER_LINK_RX_PACKETS,
|
||||
OVPN_A_PEER_LINK_TX_PACKETS,
|
||||
OVPN_A_PEER_TX_ID,
|
||||
|
||||
__OVPN_A_PEER_MAX,
|
||||
OVPN_A_PEER_MAX = (__OVPN_A_PEER_MAX - 1)
|
||||
|
|
@ -100,6 +101,7 @@ enum {
|
|||
OVPN_CMD_KEY_SWAP,
|
||||
OVPN_CMD_KEY_SWAP_NTF,
|
||||
OVPN_CMD_KEY_DEL,
|
||||
OVPN_CMD_PEER_FLOAT_NTF,
|
||||
|
||||
__OVPN_CMD_MAX,
|
||||
OVPN_CMD_MAX = (__OVPN_CMD_MAX - 1)
|
||||
|
|
|
|||
|
|
@ -2,22 +2,35 @@
|
|||
# Copyright (C) 2020-2025 OpenVPN, Inc.
|
||||
#
|
||||
CFLAGS = -pedantic -Wextra -Wall -Wl,--no-as-needed -g -O0 -ggdb $(KHDR_INCLUDES)
|
||||
CFLAGS += $(shell pkg-config --cflags mbedcrypto-3 mbedtls-3 2>/dev/null)
|
||||
|
||||
VAR_CFLAGS = $(shell pkg-config --cflags libnl-3.0 libnl-genl-3.0 2>/dev/null)
|
||||
ifeq ($(VAR_CFLAGS),)
|
||||
VAR_CFLAGS = -I/usr/include/libnl3
|
||||
endif
|
||||
CFLAGS += $(VAR_CFLAGS)
|
||||
|
||||
|
||||
LDLIBS = -lmbedtls -lmbedcrypto
|
||||
VAR_LDLIBS = $(shell pkg-config --libs libnl-3.0 libnl-genl-3.0 2>/dev/null)
|
||||
ifeq ($(VAR_LDLIBS),)
|
||||
VAR_LDLIBS = -lnl-genl-3 -lnl-3
|
||||
MTLS_LDLIBS= $(shell pkg-config --libs mbedcrypto-3 mbedtls-3 2>/dev/null)
|
||||
ifeq ($(MTLS_LDLIBS),)
|
||||
MTLS_LDLIBS = -lmbedtls -lmbedcrypto
|
||||
endif
|
||||
LDLIBS += $(VAR_LDLIBS)
|
||||
LDLIBS += $(MTLS_LDLIBS)
|
||||
|
||||
NL_LDLIBS = $(shell pkg-config --libs libnl-3.0 libnl-genl-3.0 2>/dev/null)
|
||||
ifeq ($(NL_LDLIBS),)
|
||||
NL_LDLIBS = -lnl-genl-3 -lnl-3
|
||||
endif
|
||||
LDLIBS += $(NL_LDLIBS)
|
||||
|
||||
|
||||
TEST_FILES = common.sh
|
||||
TEST_FILES = \
|
||||
common.sh \
|
||||
data64.key \
|
||||
json \
|
||||
tcp_peers.txt \
|
||||
udp_peers.txt \
|
||||
../../../../net/ynl/pyynl/cli.py \
|
||||
# end of TEST_FILES
|
||||
|
||||
TEST_PROGS := \
|
||||
test-chachapoly.sh \
|
||||
|
|
@ -25,6 +38,10 @@ TEST_PROGS := \
|
|||
test-close-socket.sh \
|
||||
test-float.sh \
|
||||
test-large-mtu.sh \
|
||||
test-mark.sh \
|
||||
test-symmetric-id-float.sh \
|
||||
test-symmetric-id-tcp.sh \
|
||||
test-symmetric-id.sh \
|
||||
test-tcp.sh \
|
||||
test.sh \
|
||||
# end of TEST_PROGS
|
||||
|
|
|
|||
|
|
@ -7,12 +7,21 @@
|
|||
UDP_PEERS_FILE=${UDP_PEERS_FILE:-udp_peers.txt}
|
||||
TCP_PEERS_FILE=${TCP_PEERS_FILE:-tcp_peers.txt}
|
||||
OVPN_CLI=${OVPN_CLI:-./ovpn-cli}
|
||||
YNL_CLI=${YNL_CLI:-../../../../net/ynl/pyynl/cli.py}
|
||||
ALG=${ALG:-aes}
|
||||
PROTO=${PROTO:-UDP}
|
||||
FLOAT=${FLOAT:-0}
|
||||
SYMMETRIC_ID=${SYMMETRIC_ID:-0}
|
||||
|
||||
export ID_OFFSET=$(( 9 * (SYMMETRIC_ID == 0) ))
|
||||
|
||||
JQ_FILTER='map(select(.msg.peer | has("remote-ipv6") | not)) |
|
||||
map(del(.msg.ifindex)) | sort_by(.msg.peer.id)[]'
|
||||
LAN_IP="11.11.11.11"
|
||||
|
||||
declare -A tmp_jsons=()
|
||||
declare -A listener_pids=()
|
||||
|
||||
create_ns() {
|
||||
ip netns add peer${1}
|
||||
}
|
||||
|
|
@ -48,27 +57,67 @@ setup_ns() {
|
|||
ip -n peer${1} link set tun${1} up
|
||||
}
|
||||
|
||||
build_capture_filter() {
|
||||
# match the first four bytes of the openvpn data payload
|
||||
if [ "${PROTO}" == "UDP" ]; then
|
||||
# For UDP, libpcap transport indexing only works for IPv4, so
|
||||
# use an explicit IPv4 or IPv6 expression based on the peer
|
||||
# address. The IPv6 branch assumes there are no extension
|
||||
# headers in the outer packet.
|
||||
if [[ "${2}" == *:* ]]; then
|
||||
printf "ip6 and ip6[6] = 17 and ip6[48:4] = %s" "${1}"
|
||||
else
|
||||
printf "ip and udp[8:4] = %s" "${1}"
|
||||
fi
|
||||
else
|
||||
# openvpn over TCP prepends a 2-byte packet length ahead of the
|
||||
# DATA_V2 opcode, so skip it before matching the payload header
|
||||
printf "ip and tcp[(((tcp[12] & 0xf0) >> 2) + 2):4] = %s" "${1}"
|
||||
fi
|
||||
}
|
||||
|
||||
setup_listener() {
|
||||
file=$(mktemp)
|
||||
PYTHONUNBUFFERED=1 ip netns exec peer${p} ${YNL_CLI} --family ovpn \
|
||||
--subscribe peers --output-json --duration 40 > ${file} &
|
||||
listener_pids[$1]=$!
|
||||
tmp_jsons[$1]="${file}"
|
||||
}
|
||||
|
||||
add_peer() {
|
||||
labels=("ASYMM" "SYMM")
|
||||
M_ID=${labels[SYMMETRIC_ID]}
|
||||
|
||||
if [ "${PROTO}" == "UDP" ]; then
|
||||
if [ ${1} -eq 0 ]; then
|
||||
ip netns exec peer0 ${OVPN_CLI} new_multi_peer tun0 1 ${UDP_PEERS_FILE}
|
||||
ip netns exec peer0 ${OVPN_CLI} new_multi_peer tun0 1 \
|
||||
${M_ID} ${UDP_PEERS_FILE}
|
||||
|
||||
for p in $(seq 1 ${NUM_PEERS}); do
|
||||
ip netns exec peer0 ${OVPN_CLI} new_key tun0 ${p} 1 0 ${ALG} 0 \
|
||||
data64.key
|
||||
done
|
||||
else
|
||||
RADDR=$(awk "NR == ${1} {print \$2}" ${UDP_PEERS_FILE})
|
||||
RPORT=$(awk "NR == ${1} {print \$3}" ${UDP_PEERS_FILE})
|
||||
LPORT=$(awk "NR == ${1} {print \$5}" ${UDP_PEERS_FILE})
|
||||
ip netns exec peer${1} ${OVPN_CLI} new_peer tun${1} ${1} ${LPORT} \
|
||||
${RADDR} ${RPORT}
|
||||
ip netns exec peer${1} ${OVPN_CLI} new_key tun${1} ${1} 1 0 ${ALG} 1 \
|
||||
data64.key
|
||||
if [ "${SYMMETRIC_ID}" -eq 1 ]; then
|
||||
PEER_ID=${1}
|
||||
TX_ID="none"
|
||||
else
|
||||
PEER_ID=$(awk "NR == ${1} {print \$2}" \
|
||||
${UDP_PEERS_FILE})
|
||||
TX_ID=${1}
|
||||
fi
|
||||
RADDR=$(awk "NR == ${1} {print \$3}" ${UDP_PEERS_FILE})
|
||||
RPORT=$(awk "NR == ${1} {print \$4}" ${UDP_PEERS_FILE})
|
||||
LPORT=$(awk "NR == ${1} {print \$6}" ${UDP_PEERS_FILE})
|
||||
ip netns exec peer${1} ${OVPN_CLI} new_peer tun${1} \
|
||||
${PEER_ID} ${TX_ID} ${LPORT} ${RADDR} ${RPORT}
|
||||
ip netns exec peer${1} ${OVPN_CLI} new_key tun${1} \
|
||||
${PEER_ID} 1 0 ${ALG} 1 data64.key
|
||||
fi
|
||||
else
|
||||
if [ ${1} -eq 0 ]; then
|
||||
(ip netns exec peer0 ${OVPN_CLI} listen tun0 1 ${TCP_PEERS_FILE} && {
|
||||
(ip netns exec peer0 ${OVPN_CLI} listen tun0 1 ${M_ID} \
|
||||
${TCP_PEERS_FILE} && {
|
||||
for p in $(seq 1 ${NUM_PEERS}); do
|
||||
ip netns exec peer0 ${OVPN_CLI} new_key tun0 ${p} 1 0 \
|
||||
${ALG} 0 data64.key
|
||||
|
|
@ -76,12 +125,40 @@ add_peer() {
|
|||
}) &
|
||||
sleep 5
|
||||
else
|
||||
ip netns exec peer${1} ${OVPN_CLI} connect tun${1} ${1} 10.10.${1}.1 1 \
|
||||
data64.key
|
||||
if [ "${SYMMETRIC_ID}" -eq 1 ]; then
|
||||
PEER_ID=${1}
|
||||
TX_ID="none"
|
||||
else
|
||||
PEER_ID=$(awk "NR == ${1} {print \$2}" \
|
||||
${TCP_PEERS_FILE})
|
||||
TX_ID=${1}
|
||||
fi
|
||||
ip netns exec peer${1} ${OVPN_CLI} connect tun${1} \
|
||||
${PEER_ID} ${TX_ID} 10.10.${1}.1 1 data64.key
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
compare_ntfs() {
|
||||
if [ ${#tmp_jsons[@]} -gt 0 ]; then
|
||||
suffix=""
|
||||
[ "${SYMMETRIC_ID}" -eq 1 ] && suffix="${suffix}-symm"
|
||||
[ "$FLOAT" == 1 ] && suffix="${suffix}-float"
|
||||
expected="json/peer${1}${suffix}.json"
|
||||
received="${tmp_jsons[$1]}"
|
||||
|
||||
kill -TERM ${listener_pids[$1]} || true
|
||||
wait ${listener_pids[$1]} || true
|
||||
printf "Checking notifications for peer ${1}... "
|
||||
if diff <(jq -s "${JQ_FILTER}" ${expected}) \
|
||||
<(jq -s "${JQ_FILTER}" ${received}); then
|
||||
echo "OK"
|
||||
fi
|
||||
|
||||
rm -f ${received} || true
|
||||
fi
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
# some ovpn-cli processes sleep in background so they need manual poking
|
||||
killall $(basename ${OVPN_CLI}) 2>/dev/null || true
|
||||
|
|
@ -104,5 +181,3 @@ if [ "${PROTO}" == "UDP" ]; then
|
|||
else
|
||||
NUM_PEERS=${NUM_PEERS:-$(wc -l ${TCP_PEERS_FILE} | awk '{print $1}')}
|
||||
fi
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1 @@
|
|||
jRqMACN7d7/aFQNT8S7jkrBD8uwrgHbG5OQZP2eu4R1Y7tfpS2bf5RHv06Vi163CGoaIiTX99R3B
|
||||
ia9ycAH8Wz1+9PWv51dnBLur9jbShlgZ2QHLtUc4a/gfT7zZwULXuuxdLnvR21DDeMBaTbkgbai9
|
||||
uvAa7ne1liIgGFzbv+Bas4HDVrygxIxuAnP5Qgc3648IJkZ0QEXPF+O9f0n5+QIvGCxkAUVx+5K6
|
||||
KIs+SoeWXnAopELmoGSjUpFtJbagXK82HfdqpuUxT2Tnuef0/14SzVE/vNleBNu2ZbyrSAaah8tE
|
||||
BofkPJUBFY+YQcfZNM5Dgrw3i+Bpmpq/gpdg5w==
|
||||
jRqMACN7d7/aFQNT8S7jkrBD8uwrgHbG5OQZP2eu4R1Y7tfpS2bf5RHv06Vi163CGoaIiTX99R3Bia9ycAH8Wz1+9PWv51dnBLur9jbShlgZ2QHLtUc4a/gfT7zZwULXuuxdLnvR21DDeMBaTbkgbai9uvAa7ne1liIgGFzbv+Bas4HDVrygxIxuAnP5Qgc3648IJkZ0QEXPF+O9f0n5+QIvGCxkAUVx+5K6KIs+SoeWXnAopELmoGSjUpFtJbagXK82HfdqpuUxT2Tnuef0/14SzVE/vNleBNu2ZbyrSAaah8tEBofkPJUBFY+YQcfZNM5Dgrw3i+Bpmpq/gpdg5w==
|
||||
|
|
|
|||
9
tools/testing/selftests/net/ovpn/json/peer0-float.json
Normal file
9
tools/testing/selftests/net/ovpn/json/peer0-float.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{"name": "peer-float-ntf", "msg": {"ifindex": 0, "peer": {"id": 1, "remote-ipv4": "10.10.1.3", "remote-port": 1}}}
|
||||
{"name": "peer-float-ntf", "msg": {"ifindex": 0, "peer": {"id": 2, "remote-ipv4": "10.10.2.3", "remote-port": 1}}}
|
||||
{"name": "peer-float-ntf", "msg": {"ifindex": 0, "peer": {"id": 3, "remote-ipv4": "10.10.3.3", "remote-port": 1}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 1}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 2}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 3}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 4}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 5}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 6}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer0-symm-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer0-symm-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer0-float.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer0-symm.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer0-symm.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer0.json
|
||||
6
tools/testing/selftests/net/ovpn/json/peer0.json
Normal file
6
tools/testing/selftests/net/ovpn/json/peer0.json
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 1}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 2}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 3}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 4}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 5}}}
|
||||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 6}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer1-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer1-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer1.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer1-symm-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer1-symm-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer1-symm.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer1-symm.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer1-symm.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 1}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer1.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer1.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 10}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer2-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer2-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer2.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer2-symm-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer2-symm-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer2-symm.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer2-symm.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer2-symm.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 2}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer2.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer2.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "userspace", "id": 11}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer3-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer3-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer3.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer3-symm-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer3-symm-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer3-symm.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer3-symm.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer3-symm.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 3}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer3.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer3.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 12}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer4-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer4-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer4.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer4-symm-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer4-symm-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer4-symm.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer4-symm.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer4-symm.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 4}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer4.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer4.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 13}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer5-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer5-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer5.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer5-symm-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer5-symm-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer5-symm.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer5-symm.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer5-symm.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 5}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer5.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer5.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 14}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer6-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer6-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer6.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer6-symm-float.json
Symbolic link
1
tools/testing/selftests/net/ovpn/json/peer6-symm-float.json
Symbolic link
|
|
@ -0,0 +1 @@
|
|||
peer6-symm.json
|
||||
1
tools/testing/selftests/net/ovpn/json/peer6-symm.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer6-symm.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 6}}}
|
||||
1
tools/testing/selftests/net/ovpn/json/peer6.json
Normal file
1
tools/testing/selftests/net/ovpn/json/peer6.json
Normal file
|
|
@ -0,0 +1 @@
|
|||
{"name": "peer-del-ntf", "msg": {"ifindex": 0, "peer": {"del-reason": "expired", "id": 15}}}
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
* Author: Antonio Quartulli <antonio@openvpn.net>
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
|
@ -103,7 +104,7 @@ struct ovpn_ctx {
|
|||
|
||||
sa_family_t sa_family;
|
||||
|
||||
unsigned long peer_id;
|
||||
unsigned long peer_id, tx_id;
|
||||
unsigned long lport;
|
||||
|
||||
union {
|
||||
|
|
@ -133,6 +134,9 @@ struct ovpn_ctx {
|
|||
enum ovpn_key_slot key_slot;
|
||||
int key_id;
|
||||
|
||||
uint32_t mark;
|
||||
bool asymm_id;
|
||||
|
||||
const char *peers_file;
|
||||
};
|
||||
|
||||
|
|
@ -521,6 +525,15 @@ static int ovpn_socket(struct ovpn_ctx *ctx, sa_family_t family, int proto)
|
|||
return ret;
|
||||
}
|
||||
|
||||
if (ctx->mark != 0) {
|
||||
ret = setsockopt(s, SOL_SOCKET, SO_MARK, (void *)&ctx->mark,
|
||||
sizeof(ctx->mark));
|
||||
if (ret < 0) {
|
||||
perror("setsockopt for SO_MARK");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (family == AF_INET6) {
|
||||
opt = 0;
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &opt,
|
||||
|
|
@ -649,6 +662,8 @@ static int ovpn_new_peer(struct ovpn_ctx *ovpn, bool is_tcp)
|
|||
|
||||
attr = nla_nest_start(ctx->nl_msg, OVPN_A_PEER);
|
||||
NLA_PUT_U32(ctx->nl_msg, OVPN_A_PEER_ID, ovpn->peer_id);
|
||||
if (ovpn->asymm_id)
|
||||
NLA_PUT_U32(ctx->nl_msg, OVPN_A_PEER_TX_ID, ovpn->tx_id);
|
||||
NLA_PUT_U32(ctx->nl_msg, OVPN_A_PEER_SOCKET, ovpn->socket);
|
||||
|
||||
if (!is_tcp) {
|
||||
|
|
@ -767,6 +782,10 @@ static int ovpn_handle_peer(struct nl_msg *msg, void (*arg)__always_unused)
|
|||
fprintf(stderr, "* Peer %u\n",
|
||||
nla_get_u32(pattrs[OVPN_A_PEER_ID]));
|
||||
|
||||
if (pattrs[OVPN_A_PEER_TX_ID])
|
||||
fprintf(stderr, "\tTX peer ID %u\n",
|
||||
nla_get_u32(pattrs[OVPN_A_PEER_TX_ID]));
|
||||
|
||||
if (pattrs[OVPN_A_PEER_SOCKET_NETNSID])
|
||||
fprintf(stderr, "\tsocket NetNS ID: %d\n",
|
||||
nla_get_s32(pattrs[OVPN_A_PEER_SOCKET_NETNSID]));
|
||||
|
|
@ -1516,6 +1535,9 @@ static int ovpn_handle_msg(struct nl_msg *msg, void *arg)
|
|||
case OVPN_CMD_PEER_DEL_NTF:
|
||||
fprintf(stdout, "received CMD_PEER_DEL_NTF\n");
|
||||
break;
|
||||
case OVPN_CMD_PEER_FLOAT_NTF:
|
||||
fprintf(stdout, "received CMD_PEER_FLOAT_NTF\n");
|
||||
break;
|
||||
case OVPN_CMD_KEY_SWAP_NTF:
|
||||
fprintf(stdout, "received CMD_KEY_SWAP_NTF\n");
|
||||
break;
|
||||
|
|
@ -1654,41 +1676,58 @@ static void usage(const char *cmd)
|
|||
fprintf(stderr, "\tiface: ovpn interface name\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"* listen <iface> <lport> <peers_file> [ipv6]: listen for incoming peer TCP connections\n");
|
||||
"* listen <iface> <lport> <id_type> <peers_file> [ipv6]: listen for incoming peer TCP connections\n");
|
||||
fprintf(stderr, "\tiface: ovpn interface name\n");
|
||||
fprintf(stderr, "\tlport: TCP port to listen to\n");
|
||||
fprintf(stderr, "\tid_type:\n");
|
||||
fprintf(stderr,
|
||||
"\t\t- SYMM for ignoring the TX peer ID from the peers_file\n");
|
||||
fprintf(stderr,
|
||||
"\t\t- ASYMM for using the TX peer ID from the peers_file\n");
|
||||
fprintf(stderr,
|
||||
"\tpeers_file: file containing one peer per line: Line format:\n");
|
||||
fprintf(stderr, "\t\t<peer_id> <vpnaddr>\n");
|
||||
fprintf(stderr, "\t\t<peer_id> <tx_id> <vpnaddr>\n");
|
||||
fprintf(stderr,
|
||||
"\tipv6: whether the socket should listen to the IPv6 wildcard address\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"* connect <iface> <peer_id> <raddr> <rport> [key_file]: start connecting peer of TCP-based VPN session\n");
|
||||
"* connect <iface> <peer_id> <tx_id> <raddr> <rport> [key_file]: start connecting peer of TCP-based VPN session\n");
|
||||
fprintf(stderr, "\tiface: ovpn interface name\n");
|
||||
fprintf(stderr, "\tpeer_id: peer ID of the connecting peer\n");
|
||||
fprintf(stderr,
|
||||
"\tpeer_id: peer ID found in data packets received from this peer\n");
|
||||
fprintf(stderr,
|
||||
"\ttx_id: peer ID to be used when sending to this peer, 'none' for symmetric peer ID\n");
|
||||
fprintf(stderr, "\traddr: peer IP address to connect to\n");
|
||||
fprintf(stderr, "\trport: peer TCP port to connect to\n");
|
||||
fprintf(stderr,
|
||||
"\tkey_file: file containing the symmetric key for encryption\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"* new_peer <iface> <peer_id> <lport> <raddr> <rport> [vpnaddr]: add new peer\n");
|
||||
"* new_peer <iface> <peer_id> <tx_id> <lport> <raddr> <rport> [vpnaddr]: add new peer\n");
|
||||
fprintf(stderr, "\tiface: ovpn interface name\n");
|
||||
fprintf(stderr, "\tlport: local UDP port to bind to\n");
|
||||
fprintf(stderr,
|
||||
"\tpeer_id: peer ID to be used in data packets to/from this peer\n");
|
||||
"\tpeer_id: peer ID found in data packets received from this peer\n");
|
||||
fprintf(stderr,
|
||||
"\ttx_id: peer ID to be used when sending to this peer, 'none' for symmetric peer ID\n");
|
||||
fprintf(stderr, "\tlport: local UDP port to bind to\n");
|
||||
fprintf(stderr, "\traddr: peer IP address\n");
|
||||
fprintf(stderr, "\trport: peer UDP port\n");
|
||||
fprintf(stderr, "\tvpnaddr: peer VPN IP\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"* new_multi_peer <iface> <lport> <peers_file>: add multiple peers as listed in the file\n");
|
||||
"* new_multi_peer <iface> <lport> <id_type> <peers_file> [mark]: add multiple peers as listed in the file\n");
|
||||
fprintf(stderr, "\tiface: ovpn interface name\n");
|
||||
fprintf(stderr, "\tlport: local UDP port to bind to\n");
|
||||
fprintf(stderr, "\tid_type:\n");
|
||||
fprintf(stderr,
|
||||
"\t\t- SYMM for ignoring the TX peer ID from the peers_file\n");
|
||||
fprintf(stderr,
|
||||
"\t\t- ASYMM for using the TX peer ID from the peers_file\n");
|
||||
fprintf(stderr,
|
||||
"\tpeers_file: text file containing one peer per line. Line format:\n");
|
||||
fprintf(stderr, "\t\t<peer_id> <raddr> <rport> <vpnaddr>\n");
|
||||
fprintf(stderr,
|
||||
"\t\t<peer_id> <tx_id> <raddr> <rport> <laddr> <lport> <vpnaddr>\n");
|
||||
fprintf(stderr, "\tmark: socket FW mark value\n");
|
||||
|
||||
fprintf(stderr,
|
||||
"* set_peer <iface> <peer_id> <keepalive_interval> <keepalive_timeout>: set peer attributes\n");
|
||||
|
|
@ -1801,15 +1840,23 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host,
|
|||
}
|
||||
|
||||
static int ovpn_parse_new_peer(struct ovpn_ctx *ovpn, const char *peer_id,
|
||||
const char *raddr, const char *rport,
|
||||
const char *vpnip)
|
||||
const char *tx_id, const char *raddr,
|
||||
const char *rport, const char *vpnip)
|
||||
{
|
||||
ovpn->peer_id = strtoul(peer_id, NULL, 10);
|
||||
if (errno == ERANGE || ovpn->peer_id > PEER_ID_UNDEF) {
|
||||
fprintf(stderr, "peer ID value out of range\n");
|
||||
fprintf(stderr, "rx peer ID value out of range\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ovpn->asymm_id) {
|
||||
ovpn->tx_id = strtoul(tx_id, NULL, 10);
|
||||
if (errno == ERANGE || ovpn->tx_id > PEER_ID_UNDEF) {
|
||||
fprintf(stderr, "tx peer ID value out of range\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ovpn_parse_remote(ovpn, raddr, rport, vpnip);
|
||||
}
|
||||
|
||||
|
|
@ -1936,8 +1983,8 @@ static void ovpn_waitbg(void)
|
|||
|
||||
static int ovpn_run_cmd(struct ovpn_ctx *ovpn)
|
||||
{
|
||||
char peer_id[10], vpnip[INET6_ADDRSTRLEN], laddr[128], lport[10];
|
||||
char raddr[128], rport[10];
|
||||
char peer_id[10], tx_id[10], vpnip[INET6_ADDRSTRLEN], laddr[128];
|
||||
char lport[10], raddr[128], rport[10];
|
||||
int n, ret;
|
||||
FILE *fp;
|
||||
|
||||
|
|
@ -1964,7 +2011,8 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn)
|
|||
|
||||
int num_peers = 0;
|
||||
|
||||
while ((n = fscanf(fp, "%s %s\n", peer_id, vpnip)) == 2) {
|
||||
while ((n = fscanf(fp, "%s %s %s\n", peer_id, tx_id,
|
||||
vpnip)) == 3) {
|
||||
struct ovpn_ctx peer_ctx = { 0 };
|
||||
|
||||
if (num_peers == MAX_PEERS) {
|
||||
|
|
@ -1974,6 +2022,7 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn)
|
|||
|
||||
peer_ctx.ifindex = ovpn->ifindex;
|
||||
peer_ctx.sa_family = ovpn->sa_family;
|
||||
peer_ctx.asymm_id = ovpn->asymm_id;
|
||||
|
||||
peer_ctx.socket = ovpn_accept(ovpn);
|
||||
if (peer_ctx.socket < 0) {
|
||||
|
|
@ -1984,8 +2033,8 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn)
|
|||
/* store peer sockets to test TCP I/O */
|
||||
ovpn->cli_sockets[num_peers] = peer_ctx.socket;
|
||||
|
||||
ret = ovpn_parse_new_peer(&peer_ctx, peer_id, NULL,
|
||||
NULL, vpnip);
|
||||
ret = ovpn_parse_new_peer(&peer_ctx, peer_id, tx_id,
|
||||
NULL, NULL, vpnip);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "error while parsing line\n");
|
||||
return -1;
|
||||
|
|
@ -2053,16 +2102,17 @@ static int ovpn_run_cmd(struct ovpn_ctx *ovpn)
|
|||
return -1;
|
||||
}
|
||||
|
||||
while ((n = fscanf(fp, "%s %s %s %s %s %s\n", peer_id, laddr,
|
||||
lport, raddr, rport, vpnip)) == 6) {
|
||||
while ((n = fscanf(fp, "%s %s %s %s %s %s %s\n", peer_id, tx_id,
|
||||
laddr, lport, raddr, rport, vpnip)) == 7) {
|
||||
struct ovpn_ctx peer_ctx = { 0 };
|
||||
|
||||
peer_ctx.ifindex = ovpn->ifindex;
|
||||
peer_ctx.socket = ovpn->socket;
|
||||
peer_ctx.sa_family = AF_UNSPEC;
|
||||
peer_ctx.asymm_id = ovpn->asymm_id;
|
||||
|
||||
ret = ovpn_parse_new_peer(&peer_ctx, peer_id, raddr,
|
||||
rport, vpnip);
|
||||
ret = ovpn_parse_new_peer(&peer_ctx, peer_id, tx_id,
|
||||
raddr, rport, vpnip);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "error while parsing line\n");
|
||||
return -1;
|
||||
|
|
@ -2158,7 +2208,7 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[])
|
|||
case CMD_DEL_IFACE:
|
||||
break;
|
||||
case CMD_LISTEN:
|
||||
if (argc < 5)
|
||||
if (argc < 6)
|
||||
return -EINVAL;
|
||||
|
||||
ovpn->lport = strtoul(argv[3], NULL, 10);
|
||||
|
|
@ -2167,55 +2217,67 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
ovpn->peers_file = argv[4];
|
||||
if (strcmp(argv[4], "SYMM") == 0) {
|
||||
ovpn->asymm_id = false;
|
||||
} else if (strcmp(argv[4], "ASYMM") == 0) {
|
||||
ovpn->asymm_id = true;
|
||||
} else {
|
||||
fprintf(stderr, "Cannot parse id type: %s\n", argv[4]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ovpn->peers_file = argv[5];
|
||||
|
||||
ovpn->sa_family = AF_INET;
|
||||
if (argc > 5 && !strcmp(argv[5], "ipv6"))
|
||||
if (argc > 6 && !strcmp(argv[6], "ipv6"))
|
||||
ovpn->sa_family = AF_INET6;
|
||||
break;
|
||||
case CMD_CONNECT:
|
||||
if (argc < 6)
|
||||
if (argc < 7)
|
||||
return -EINVAL;
|
||||
|
||||
ovpn->sa_family = AF_INET;
|
||||
ovpn->asymm_id = strcmp(argv[4], "none");
|
||||
|
||||
ret = ovpn_parse_new_peer(ovpn, argv[3], argv[4], argv[5],
|
||||
NULL);
|
||||
argv[6], NULL);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Cannot parse remote peer data\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (argc > 6) {
|
||||
if (argc > 7) {
|
||||
ovpn->key_slot = OVPN_KEY_SLOT_PRIMARY;
|
||||
ovpn->key_id = 0;
|
||||
ovpn->cipher = OVPN_CIPHER_ALG_AES_GCM;
|
||||
ovpn->key_dir = KEY_DIR_OUT;
|
||||
|
||||
ret = ovpn_parse_key(argv[6], ovpn);
|
||||
ret = ovpn_parse_key(argv[7], ovpn);
|
||||
if (ret)
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case CMD_NEW_PEER:
|
||||
if (argc < 7)
|
||||
if (argc < 8)
|
||||
return -EINVAL;
|
||||
|
||||
ovpn->lport = strtoul(argv[4], NULL, 10);
|
||||
ovpn->asymm_id = strcmp(argv[4], "none");
|
||||
|
||||
ovpn->lport = strtoul(argv[5], NULL, 10);
|
||||
if (errno == ERANGE || ovpn->lport > 65535) {
|
||||
fprintf(stderr, "lport value out of range\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *vpnip = (argc > 7) ? argv[7] : NULL;
|
||||
const char *vpnip = (argc > 8) ? argv[8] : NULL;
|
||||
|
||||
ret = ovpn_parse_new_peer(ovpn, argv[3], argv[5], argv[6],
|
||||
vpnip);
|
||||
ret = ovpn_parse_new_peer(ovpn, argv[3], argv[4], argv[6],
|
||||
argv[7], vpnip);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
break;
|
||||
case CMD_NEW_MULTI_PEER:
|
||||
if (argc < 5)
|
||||
if (argc < 6)
|
||||
return -EINVAL;
|
||||
|
||||
ovpn->lport = strtoul(argv[3], NULL, 10);
|
||||
|
|
@ -2224,7 +2286,25 @@ static int ovpn_parse_cmd_args(struct ovpn_ctx *ovpn, int argc, char *argv[])
|
|||
return -1;
|
||||
}
|
||||
|
||||
ovpn->peers_file = argv[4];
|
||||
if (!strcmp(argv[4], "SYMM")) {
|
||||
ovpn->asymm_id = false;
|
||||
} else if (!strcmp(argv[4], "ASYMM")) {
|
||||
ovpn->asymm_id = true;
|
||||
} else {
|
||||
fprintf(stderr, "Cannot parse id type: %s\n", argv[4]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ovpn->peers_file = argv[5];
|
||||
|
||||
ovpn->mark = 0;
|
||||
if (argc > 6) {
|
||||
ovpn->mark = strtoul(argv[6], NULL, 10);
|
||||
if (errno == ERANGE || ovpn->mark > UINT32_MAX) {
|
||||
fprintf(stderr, "mark value out of range\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CMD_SET_PEER:
|
||||
if (argc < 6)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
1 5.5.5.2
|
||||
2 5.5.5.3
|
||||
3 5.5.5.4
|
||||
4 5.5.5.5
|
||||
5 5.5.5.6
|
||||
1 10 5.5.5.2
|
||||
2 11 5.5.5.3
|
||||
3 12 5.5.5.4
|
||||
4 13 5.5.5.5
|
||||
5 14 5.5.5.6
|
||||
6 15 5.5.5.7
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ done
|
|||
|
||||
for p in $(seq 1 ${NUM_PEERS}); do
|
||||
ip netns exec peer0 ${OVPN_CLI} set_peer tun0 ${p} 60 120
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} ${p} 60 120
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} $((${p}+9)) 60 120
|
||||
done
|
||||
|
||||
sleep 1
|
||||
|
|
|
|||
96
tools/testing/selftests/net/ovpn/test-mark.sh
Executable file
96
tools/testing/selftests/net/ovpn/test-mark.sh
Executable file
|
|
@ -0,0 +1,96 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (C) 2020-2025 OpenVPN, Inc.
|
||||
#
|
||||
# Author: Ralf Lici <ralf@mandelbit.com>
|
||||
# Antonio Quartulli <antonio@openvpn.net>
|
||||
|
||||
#set -x
|
||||
set -e
|
||||
|
||||
MARK=1056
|
||||
|
||||
source ./common.sh
|
||||
|
||||
cleanup
|
||||
|
||||
modprobe -q ovpn || true
|
||||
|
||||
for p in $(seq 0 "${NUM_PEERS}"); do
|
||||
create_ns "${p}"
|
||||
done
|
||||
|
||||
for p in $(seq 0 3); do
|
||||
setup_ns "${p}" 5.5.5.$((p + 1))/24
|
||||
done
|
||||
|
||||
# add peer0 with mark
|
||||
ip netns exec peer0 "${OVPN_CLI}" new_multi_peer tun0 1 ASYMM \
|
||||
"${UDP_PEERS_FILE}" \
|
||||
${MARK}
|
||||
for p in $(seq 1 3); do
|
||||
ip netns exec peer0 "${OVPN_CLI}" new_key tun0 "${p}" 1 0 "${ALG}" 0 \
|
||||
data64.key
|
||||
done
|
||||
|
||||
for p in $(seq 1 3); do
|
||||
add_peer "${p}"
|
||||
done
|
||||
|
||||
for p in $(seq 1 3); do
|
||||
ip netns exec peer0 "${OVPN_CLI}" set_peer tun0 "${p}" 60 120
|
||||
ip netns exec peer"${p}" "${OVPN_CLI}" set_peer tun"${p}" \
|
||||
$((p + 9)) 60 120
|
||||
done
|
||||
|
||||
sleep 1
|
||||
|
||||
for p in $(seq 1 3); do
|
||||
ip netns exec peer0 ping -qfc 500 -w 3 5.5.5.$((p + 1))
|
||||
done
|
||||
|
||||
echo "Adding an nftables drop rule based on mark value ${MARK}"
|
||||
ip netns exec peer0 nft flush ruleset
|
||||
ip netns exec peer0 nft 'add table inet filter'
|
||||
ip netns exec peer0 nft 'add chain inet filter output {
|
||||
type filter hook output priority 0;
|
||||
policy accept;
|
||||
}'
|
||||
ip netns exec peer0 nft add rule inet filter output \
|
||||
meta mark == ${MARK} \
|
||||
counter drop
|
||||
|
||||
DROP_COUNTER=$(ip netns exec peer0 nft list chain inet filter output \
|
||||
| sed -n 's/.*packets \([0-9]*\).*/\1/p')
|
||||
sleep 1
|
||||
|
||||
# ping should fail
|
||||
for p in $(seq 1 3); do
|
||||
PING_OUTPUT=$(ip netns exec peer0 ping \
|
||||
-qfc 500 -w 1 5.5.5.$((p + 1)) 2>&1) && exit 1
|
||||
echo "${PING_OUTPUT}"
|
||||
LOST_PACKETS=$(echo "$PING_OUTPUT" \
|
||||
| awk '/packets transmitted/ { print $1 }')
|
||||
# increment the drop counter by the amount of lost packets
|
||||
DROP_COUNTER=$((DROP_COUNTER + LOST_PACKETS))
|
||||
done
|
||||
|
||||
# check if the final nft counter matches our counter
|
||||
TOTAL_COUNT=$(ip netns exec peer0 nft list chain inet filter output \
|
||||
| sed -n 's/.*packets \([0-9]*\).*/\1/p')
|
||||
if [ "${DROP_COUNTER}" -ne "${TOTAL_COUNT}" ]; then
|
||||
echo "Expected ${TOTAL_COUNT} drops, got ${DROP_COUNTER}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Removing the drop rule"
|
||||
ip netns exec peer0 nft flush ruleset
|
||||
sleep 1
|
||||
|
||||
for p in $(seq 1 3); do
|
||||
ip netns exec peer0 ping -qfc 500 -w 3 5.5.5.$((p + 1))
|
||||
done
|
||||
|
||||
cleanup
|
||||
|
||||
modprobe -r ovpn || true
|
||||
11
tools/testing/selftests/net/ovpn/test-symmetric-id-float.sh
Executable file
11
tools/testing/selftests/net/ovpn/test-symmetric-id-float.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (C) 2025 OpenVPN, Inc.
|
||||
#
|
||||
# Author: Ralf Lici <ralf@mandelbit.com>
|
||||
# Antonio Quartulli <antonio@openvpn.net>
|
||||
|
||||
SYMMETRIC_ID="1"
|
||||
FLOAT="1"
|
||||
|
||||
source test.sh
|
||||
11
tools/testing/selftests/net/ovpn/test-symmetric-id-tcp.sh
Executable file
11
tools/testing/selftests/net/ovpn/test-symmetric-id-tcp.sh
Executable file
|
|
@ -0,0 +1,11 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (C) 2025 OpenVPN, Inc.
|
||||
#
|
||||
# Author: Ralf Lici <ralf@mandelbit.com>
|
||||
# Antonio Quartulli <antonio@openvpn.net>
|
||||
|
||||
PROTO="TCP"
|
||||
SYMMETRIC_ID=1
|
||||
|
||||
source test.sh
|
||||
10
tools/testing/selftests/net/ovpn/test-symmetric-id.sh
Executable file
10
tools/testing/selftests/net/ovpn/test-symmetric-id.sh
Executable file
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/bash
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
# Copyright (C) 2025 OpenVPN, Inc.
|
||||
#
|
||||
# Author: Ralf Lici <ralf@mandelbit.com>
|
||||
# Antonio Quartulli <antonio@openvpn.net>
|
||||
|
||||
SYMMETRIC_ID="1"
|
||||
|
||||
source test.sh
|
||||
|
|
@ -17,6 +17,10 @@ for p in $(seq 0 ${NUM_PEERS}); do
|
|||
create_ns ${p}
|
||||
done
|
||||
|
||||
for p in $(seq 0 ${NUM_PEERS}); do
|
||||
setup_listener ${p}
|
||||
done
|
||||
|
||||
for p in $(seq 0 ${NUM_PEERS}); do
|
||||
setup_ns ${p} 5.5.5.$((${p} + 1))/24 ${MTU}
|
||||
done
|
||||
|
|
@ -27,14 +31,45 @@ done
|
|||
|
||||
for p in $(seq 1 ${NUM_PEERS}); do
|
||||
ip netns exec peer0 ${OVPN_CLI} set_peer tun0 ${p} 60 120
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} ${p} 60 120
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} \
|
||||
$((${p}+ID_OFFSET)) 60 120
|
||||
done
|
||||
|
||||
sleep 1
|
||||
|
||||
TCPDUMP_TIMEOUT="1.5s"
|
||||
for p in $(seq 1 ${NUM_PEERS}); do
|
||||
# The first part of the data packet header consists of:
|
||||
# - TCP only: 2 bytes for the packet length
|
||||
# - 5 bits for opcode ("9" for DATA_V2)
|
||||
# - 3 bits for key-id ("0" at this point)
|
||||
# - 12 bytes for peer-id:
|
||||
# - with asymmetric ID: "${p}" one way and "${p} + 9" the other way
|
||||
# - with symmetric ID: "${p}" both ways
|
||||
HEADER1=$(printf "0x4800000%x" ${p})
|
||||
HEADER2=$(printf "0x4800000%x" $((${p} + ID_OFFSET)))
|
||||
RADDR=""
|
||||
if [ "${PROTO}" == "UDP" ]; then
|
||||
RADDR=$(awk "NR == ${p} {print \$3}" ${UDP_PEERS_FILE})
|
||||
fi
|
||||
|
||||
timeout ${TCPDUMP_TIMEOUT} ip netns exec peer${p} \
|
||||
tcpdump --immediate-mode -p -ni veth${p} -c 1 \
|
||||
"$(build_capture_filter "${HEADER1}" "${RADDR}")" \
|
||||
>/dev/null 2>&1 &
|
||||
TCPDUMP_PID1=$!
|
||||
timeout ${TCPDUMP_TIMEOUT} ip netns exec peer${p} \
|
||||
tcpdump --immediate-mode -p -ni veth${p} -c 1 \
|
||||
"$(build_capture_filter "${HEADER2}" "${RADDR}")" \
|
||||
>/dev/null 2>&1 &
|
||||
TCPDUMP_PID2=$!
|
||||
|
||||
sleep 0.3
|
||||
ip netns exec peer0 ping -qfc 500 -w 3 5.5.5.$((${p} + 1))
|
||||
ip netns exec peer0 ping -qfc 500 -s 3000 -w 3 5.5.5.$((${p} + 1))
|
||||
|
||||
wait ${TCPDUMP_PID1}
|
||||
wait ${TCPDUMP_PID2}
|
||||
done
|
||||
|
||||
# ping LAN behind client 1
|
||||
|
|
@ -57,9 +92,12 @@ ip netns exec peer1 iperf3 -Z -t 3 -c 5.5.5.1
|
|||
|
||||
echo "Adding secondary key and then swap:"
|
||||
for p in $(seq 1 ${NUM_PEERS}); do
|
||||
ip netns exec peer0 ${OVPN_CLI} new_key tun0 ${p} 2 1 ${ALG} 0 data64.key
|
||||
ip netns exec peer${p} ${OVPN_CLI} new_key tun${p} ${p} 2 1 ${ALG} 1 data64.key
|
||||
ip netns exec peer${p} ${OVPN_CLI} swap_keys tun${p} ${p}
|
||||
ip netns exec peer0 ${OVPN_CLI} new_key tun0 ${p} 2 1 ${ALG} 0 \
|
||||
data64.key
|
||||
ip netns exec peer${p} ${OVPN_CLI} new_key tun${p} \
|
||||
$((${p} + ID_OFFSET)) 2 1 ${ALG} 1 data64.key
|
||||
ip netns exec peer${p} ${OVPN_CLI} swap_keys tun${p} \
|
||||
$((${p} + ID_OFFSET))
|
||||
done
|
||||
|
||||
sleep 1
|
||||
|
|
@ -71,17 +109,19 @@ ip netns exec peer1 ${OVPN_CLI} get_peer tun1
|
|||
echo "Querying peer 1:"
|
||||
ip netns exec peer0 ${OVPN_CLI} get_peer tun0 1
|
||||
|
||||
echo "Querying non-existent peer 10:"
|
||||
ip netns exec peer0 ${OVPN_CLI} get_peer tun0 10 || true
|
||||
echo "Querying non-existent peer 20:"
|
||||
ip netns exec peer0 ${OVPN_CLI} get_peer tun0 20 || true
|
||||
|
||||
echo "Deleting peer 1:"
|
||||
ip netns exec peer0 ${OVPN_CLI} del_peer tun0 1
|
||||
ip netns exec peer1 ${OVPN_CLI} del_peer tun1 1
|
||||
ip netns exec peer1 ${OVPN_CLI} del_peer tun1 $((1 + ID_OFFSET))
|
||||
|
||||
echo "Querying keys:"
|
||||
for p in $(seq 2 ${NUM_PEERS}); do
|
||||
ip netns exec peer${p} ${OVPN_CLI} get_key tun${p} ${p} 1
|
||||
ip netns exec peer${p} ${OVPN_CLI} get_key tun${p} ${p} 2
|
||||
ip netns exec peer${p} ${OVPN_CLI} get_key tun${p} \
|
||||
$((${p} + ID_OFFSET)) 1
|
||||
ip netns exec peer${p} ${OVPN_CLI} get_key tun${p} \
|
||||
$((${p} + ID_OFFSET)) 2
|
||||
done
|
||||
|
||||
echo "Deleting peer while sending traffic:"
|
||||
|
|
@ -90,28 +130,36 @@ sleep 2
|
|||
ip netns exec peer0 ${OVPN_CLI} del_peer tun0 2
|
||||
# following command fails in TCP mode
|
||||
# (both ends get conn reset when one peer disconnects)
|
||||
ip netns exec peer2 ${OVPN_CLI} del_peer tun2 2 || true
|
||||
ip netns exec peer2 ${OVPN_CLI} del_peer tun2 $((2 + ID_OFFSET)) || true
|
||||
|
||||
echo "Deleting keys:"
|
||||
for p in $(seq 3 ${NUM_PEERS}); do
|
||||
ip netns exec peer${p} ${OVPN_CLI} del_key tun${p} ${p} 1
|
||||
ip netns exec peer${p} ${OVPN_CLI} del_key tun${p} ${p} 2
|
||||
ip netns exec peer${p} ${OVPN_CLI} del_key tun${p} \
|
||||
$((${p} + ID_OFFSET)) 1
|
||||
ip netns exec peer${p} ${OVPN_CLI} del_key tun${p} \
|
||||
$((${p} + ID_OFFSET)) 2
|
||||
done
|
||||
|
||||
echo "Setting timeout to 3s MP:"
|
||||
for p in $(seq 3 ${NUM_PEERS}); do
|
||||
ip netns exec peer0 ${OVPN_CLI} set_peer tun0 ${p} 3 3 || true
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} ${p} 0 0
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} \
|
||||
$((${p} + ID_OFFSET)) 0 0
|
||||
done
|
||||
# wait for peers to timeout
|
||||
sleep 5
|
||||
|
||||
echo "Setting timeout to 3s P2P:"
|
||||
for p in $(seq 3 ${NUM_PEERS}); do
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} ${p} 3 3
|
||||
ip netns exec peer${p} ${OVPN_CLI} set_peer tun${p} \
|
||||
$((${p} + ID_OFFSET)) 3 3
|
||||
done
|
||||
sleep 5
|
||||
|
||||
for p in $(seq 0 ${NUM_PEERS}); do
|
||||
compare_ntfs ${p}
|
||||
done
|
||||
|
||||
cleanup
|
||||
|
||||
modprobe -r ovpn || true
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
1 10.10.1.1 1 10.10.1.2 1 5.5.5.2
|
||||
2 10.10.2.1 1 10.10.2.2 1 5.5.5.3
|
||||
3 10.10.3.1 1 10.10.3.2 1 5.5.5.4
|
||||
4 fd00:0:0:4::1 1 fd00:0:0:4::2 1 5.5.5.5
|
||||
5 fd00:0:0:5::1 1 fd00:0:0:5::2 1 5.5.5.6
|
||||
6 fd00:0:0:6::1 1 fd00:0:0:6::2 1 5.5.5.7
|
||||
1 10 10.10.1.1 1 10.10.1.2 1 5.5.5.2
|
||||
2 11 10.10.2.1 1 10.10.2.2 1 5.5.5.3
|
||||
3 12 10.10.3.1 1 10.10.3.2 1 5.5.5.4
|
||||
4 13 fd00:0:0:4::1 1 fd00:0:0:4::2 1 5.5.5.5
|
||||
5 14 fd00:0:0:5::1 1 fd00:0:0:5::2 1 5.5.5.6
|
||||
6 15 fd00:0:0:6::1 1 fd00:0:0:6::2 1 5.5.5.7
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user