/** * ovpn_is_keepalive - check if skb contains a keepalive message * @skb: packet to check * * Assumes that the first byte of skb->data is defined. * * Return: true if skb contains a keepalive or false otherwise
*/ staticbool ovpn_is_keepalive(struct sk_buff *skb)
{ if (*skb->data != ovpn_keepalive_message[0]) returnfalse;
if (skb->len != OVPN_KEEPALIVE_SIZE) returnfalse;
if (!pskb_may_pull(skb, OVPN_KEEPALIVE_SIZE)) returnfalse;
/* Called after decrypt to write the IP packet to the device. * This method is expected to manage/free the skb.
*/ staticvoid ovpn_netdev_write(struct ovpn_peer *peer, struct sk_buff *skb)
{ unsignedint pkt_len; int ret;
/* * GSO state from the transport layer is not valid for the tunnel/data * path. Reset all GSO fields to prevent any further GSO processing * from entering an inconsistent state.
*/
skb_gso_reset(skb);
/* we can't guarantee the packet wasn't corrupted before entering the * VPN, therefore we give other layers a chance to check that
*/
skb->ip_summed = CHECKSUM_NONE;
/* skb hash for transport packet no longer valid after decapsulation */
skb_clear_hash(skb);
/* post-decrypt scrub -- prepare to inject encapsulated packet onto the * interface, based on __skb_tunnel_rx() in dst.h
*/
skb->dev = peer->ovpn->dev;
skb_set_queue_mapping(skb, 0);
skb_scrub_packet(skb, true);
/* network header reset in ovpn_decrypt_post() */
skb_reset_transport_header(skb);
skb_reset_inner_headers(skb);
/* cause packet to be "received" by the interface */
pkt_len = skb->len;
ret = gro_cells_receive(&peer->ovpn->gro_cells, skb); if (likely(ret == NET_RX_SUCCESS)) { /* update RX stats with the size of decrypted packet */
ovpn_peer_stats_increment_rx(&peer->vpn_stats, pkt_len);
dev_dstats_rx_add(peer->ovpn->dev, pkt_len);
}
}
/* crypto is happening asynchronously. this function will be called * again later by the crypto callback with a proper return code
*/ if (unlikely(ret == -EINPROGRESS)) return;
/* 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);
if (unlikely(ret < 0)) goto drop;
/* PID sits after the op */
pid = (__force __be32 *)(skb->data + OVPN_OPCODE_SIZE);
ret = ovpn_pktid_recv(&ks->pid_recv, ntohl(*pid), 0); if (unlikely(ret < 0)) {
net_err_ratelimited("%s: PKT ID RX error for peer %u: %d\n",
netdev_name(peer->ovpn->dev), peer->id,
ret); goto drop;
}
/* keep track of last received authenticated packet for keepalive */
WRITE_ONCE(peer->last_recv, ktime_get_real_seconds());
rcu_read_lock();
sock = rcu_dereference(peer->sock); if (sock && sock->sk->sk_protocol == IPPROTO_UDP) /* check if this peer changed local or remote endpoint */
ovpn_peer_endpoints_update(peer, skb);
rcu_read_unlock();
/* point to encapsulated IP packet */
__skb_pull(skb, payload_offset);
/* check if this is a valid datapacket that has to be delivered to the * ovpn interface
*/
skb_reset_network_header(skb);
proto = ovpn_ip_check_protocol(skb); if (unlikely(!proto)) { /* check if null packet */ if (unlikely(!pskb_may_pull(skb, 1))) {
net_info_ratelimited("%s: NULL packet received from peer %u\n",
netdev_name(peer->ovpn->dev),
peer->id); goto drop;
}
if (ovpn_is_keepalive(skb)) {
net_dbg_ratelimited("%s: ping received from peer %u\n",
netdev_name(peer->ovpn->dev),
peer->id); /* we drop the packet, but this is not a failure */
consume_skb(skb); goto drop_nocount;
}
net_info_ratelimited("%s: unsupported protocol received from peer %u\n",
netdev_name(peer->ovpn->dev), peer->id); goto drop;
}
skb->protocol = proto;
ovpn_netdev_write(peer, skb); /* skb is passed to upper layer - don't free it */
skb = NULL;
drop: if (unlikely(skb))
dev_dstats_rx_dropped(peer->ovpn->dev);
kfree_skb(skb);
drop_nocount: if (likely(peer))
ovpn_peer_put(peer); if (likely(ks))
ovpn_crypto_key_slot_put(ks);
}
/* RX path entry point: decrypt packet and forward it to the device */ void ovpn_recv(struct ovpn_peer *peer, struct sk_buff *skb)
{ struct ovpn_crypto_key_slot *ks;
u8 key_id;
/* get the key slot matching the key ID in the received packet */
key_id = ovpn_key_id_from_skb(skb);
ks = ovpn_crypto_key_id_to_slot(&peer->crypto, key_id); if (unlikely(!ks)) {
net_info_ratelimited("%s: no available key for peer %u, key-id: %u\n",
netdev_name(peer->ovpn->dev), peer->id,
key_id);
dev_dstats_rx_dropped(peer->ovpn->dev);
kfree_skb(skb);
ovpn_peer_put(peer); return;
}
/* encryption is happening asynchronously. This function will be * called later by the crypto callback with a proper return value
*/ if (unlikely(ret == -EINPROGRESS)) return;
/* 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);
if (unlikely(ret == -ERANGE)) { /* we ran out of IVs and we must kill the key as it can't be * use anymore
*/
netdev_warn(peer->ovpn->dev, "killing key %u for peer %u\n", ks->key_id,
peer->id); if (ovpn_crypto_kill_key(&peer->crypto, ks->key_id)) /* let userspace know so that a new key must be negotiated */
ovpn_nl_key_swap_notify(peer, ks->key_id);
goto err;
}
if (unlikely(ret < 0)) goto err;
skb_mark_not_on_list(skb);
orig_len = skb->len;
rcu_read_lock();
sock = rcu_dereference(peer->sock); if (unlikely(!sock)) goto err_unlock;
switch (sock->sk->sk_protocol) { case IPPROTO_UDP:
ovpn_udp_send_skb(peer, sock->sk, skb); break; case IPPROTO_TCP:
ovpn_tcp_send_skb(peer, sock->sk, skb); break; default: /* no transport configured yet */ goto err_unlock;
}
ovpn_peer_stats_increment_tx(&peer->link_stats, orig_len); /* keep track of last sent packet for keepalive */
WRITE_ONCE(peer->last_sent, ktime_get_real_seconds()); /* skb passed down the stack - don't free it */
skb = NULL;
err_unlock:
rcu_read_unlock();
err: if (unlikely(skb))
dev_dstats_tx_dropped(peer->ovpn->dev); if (likely(peer))
ovpn_peer_put(peer); if (likely(ks))
ovpn_crypto_key_slot_put(ks);
kfree_skb(skb);
}
/* get primary key to be used for encrypting data */
ks = ovpn_crypto_key_slot_primary(&peer->crypto); if (unlikely(!ks)) returnfalse;
/* take a reference to the peer because the crypto code may run async. * ovpn_encrypt_post() will release it upon completion
*/ if (unlikely(!ovpn_peer_hold(peer))) {
DEBUG_NET_WARN_ON_ONCE(1);
ovpn_crypto_key_slot_put(ks); returnfalse;
}
/* send skb to connected peer, if any */ staticvoid ovpn_send(struct ovpn_priv *ovpn, struct sk_buff *skb, struct ovpn_peer *peer)
{ struct sk_buff *curr, *next;
/* this might be a GSO-segmented skb list: process each skb * independently
*/
skb_list_walk_safe(skb, curr, next) { if (unlikely(!ovpn_encrypt_one(peer, curr))) {
dev_dstats_tx_dropped(ovpn->dev);
kfree_skb(curr);
}
}
ovpn_peer_put(peer);
}
/* Send user data to the network
*/
netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)
{ struct ovpn_priv *ovpn = netdev_priv(dev); struct sk_buff *segments, *curr, *next; struct sk_buff_head skb_list; struct ovpn_peer *peer;
__be16 proto; int ret;
/* reset netfilter state */
nf_reset_ct(skb);
/* verify IP header size in network packet */
proto = ovpn_ip_check_protocol(skb); if (unlikely(!proto || skb->protocol != proto)) goto drop;
if (skb_is_gso(skb)) {
segments = skb_gso_segment(skb, 0); if (IS_ERR(segments)) {
ret = PTR_ERR(segments);
net_err_ratelimited("%s: cannot segment payload packet: %d\n",
netdev_name(dev), ret); goto drop;
}
/* retrieve peer serving the destination IP of this packet */
peer = ovpn_peer_get_by_dst(ovpn, skb); if (unlikely(!peer)) { switch (skb->protocol) { case htons(ETH_P_IP):
net_dbg_ratelimited("%s: no peer to send data to dst=%pI4\n",
netdev_name(ovpn->dev),
&ip_hdr(skb)->daddr); break; case htons(ETH_P_IPV6):
net_dbg_ratelimited("%s: no peer to send data to dst=%pI6c\n",
netdev_name(ovpn->dev),
&ipv6_hdr(skb)->daddr); break;
} goto drop;
} /* dst was needed for peer selection - it can now be dropped */
skb_dst_drop(skb);
/** * ovpn_xmit_special - encrypt and transmit an out-of-band message to peer * @peer: peer to send the message to * @data: message content * @len: message length * * Assumes that caller holds a reference to peer, which will be * passed to ovpn_send()
*/ void ovpn_xmit_special(struct ovpn_peer *peer, constvoid *data, constunsignedint len)
{ struct ovpn_priv *ovpn; struct sk_buff *skb;
ovpn = peer->ovpn; if (unlikely(!ovpn)) {
ovpn_peer_put(peer); return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.