Changeset View
Changeset View
Standalone View
Standalone View
sys/net/if_ovpn.c
Show First 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | struct ovpn_kkey_dir { | ||||
crypto_session_t cryptoid; | crypto_session_t cryptoid; | ||||
struct mtx replay_mtx; | struct mtx replay_mtx; | ||||
/* | /* | ||||
* Last seen gapless sequence number. New rx seq numbers must be | * Last seen gapless sequence number. New rx seq numbers must be | ||||
* strictly higher than this. | * strictly higher than this. | ||||
*/ | */ | ||||
uint32_t rx_seq; | uint32_t rx_seq; | ||||
uint32_t tx_seq; | uint64_t tx_seq; | ||||
/* Seen packets, relative to rx_seq. bit(0) will always be 0. */ | /* Seen packets, relative to rx_seq. bit(0) will always be 0. */ | ||||
uint64_t rx_window; | uint64_t rx_window; | ||||
}; | }; | ||||
struct ovpn_kkey { | struct ovpn_kkey { | ||||
struct ovpn_kkey_dir *encrypt; | struct ovpn_kkey_dir *encrypt; | ||||
struct ovpn_kkey_dir *decrypt; | struct ovpn_kkey_dir *decrypt; | ||||
▲ Show 20 Lines • Show All 1,720 Lines • ▼ Show 20 Lines | |||||
ovpn_transmit_to_peer(struct ifnet *ifp, struct mbuf *m, | ovpn_transmit_to_peer(struct ifnet *ifp, struct mbuf *m, | ||||
struct ovpn_kpeer *peer, struct rm_priotracker *_ovpn_lock_trackerp) | struct ovpn_kpeer *peer, struct rm_priotracker *_ovpn_lock_trackerp) | ||||
{ | { | ||||
struct ovpn_wire_header *ohdr; | struct ovpn_wire_header *ohdr; | ||||
struct ovpn_kkey *key; | struct ovpn_kkey *key; | ||||
struct ovpn_softc *sc; | struct ovpn_softc *sc; | ||||
struct cryptop *crp; | struct cryptop *crp; | ||||
uint32_t af, seq; | uint32_t af, seq; | ||||
uint64_t seq64; | |||||
size_t len, ovpn_hdr_len; | size_t len, ovpn_hdr_len; | ||||
int tunnel_len; | int tunnel_len; | ||||
int ret; | int ret; | ||||
sc = ifp->if_softc; | sc = ifp->if_softc; | ||||
OVPN_RASSERT(sc); | OVPN_RASSERT(sc); | ||||
Show All 27 Lines | if (m == NULL) { | ||||
return (ENOBUFS); | return (ENOBUFS); | ||||
} | } | ||||
ohdr = mtod(m, struct ovpn_wire_header *); | ohdr = mtod(m, struct ovpn_wire_header *); | ||||
ohdr->opcode = (OVPN_OP_DATA_V2 << OVPN_OP_SHIFT) | key->keyid; | ohdr->opcode = (OVPN_OP_DATA_V2 << OVPN_OP_SHIFT) | key->keyid; | ||||
ohdr->opcode <<= 24; | ohdr->opcode <<= 24; | ||||
ohdr->opcode |= key->peerid; | ohdr->opcode |= key->peerid; | ||||
ohdr->opcode = htonl(ohdr->opcode); | ohdr->opcode = htonl(ohdr->opcode); | ||||
seq = atomic_fetchadd_32(&peer->keys[OVPN_KEY_SLOT_PRIMARY].encrypt->tx_seq, 1); | seq64 = atomic_fetchadd_64(&peer->keys[OVPN_KEY_SLOT_PRIMARY].encrypt->tx_seq, 1); | ||||
if (seq == OVPN_SEQ_ROTATE) | if (seq64 == OVPN_SEQ_ROTATE) { | ||||
ovpn_notify_key_rotation(sc, peer); | ovpn_notify_key_rotation(sc, peer); | ||||
} else if (seq64 > UINT32_MAX) { | |||||
/* We've wrapped, give up on this packet. */ | |||||
if (_ovpn_lock_trackerp != NULL) | |||||
OVPN_RUNLOCK(sc); | |||||
OVPN_COUNTER_ADD(sc, nomem_data_pkts_out, 1); | |||||
seq = htonl(seq); | /* Let's avoid (very unlikely, but still) wraparounds of the | ||||
* 64-bit counter taking us back to 0. */ | |||||
atomic_set_64(&peer->keys[OVPN_KEY_SLOT_PRIMARY].encrypt->tx_seq, | |||||
UINT32_MAX); | |||||
return (ENOBUFS); | |||||
} | |||||
seq = htonl(seq64 & UINT32_MAX); | |||||
ohdr->seq = seq; | ohdr->seq = seq; | ||||
OVPN_PEER_COUNTER_ADD(peer, pkt_out, 1); | OVPN_PEER_COUNTER_ADD(peer, pkt_out, 1); | ||||
OVPN_PEER_COUNTER_ADD(peer, bytes_out, len); | OVPN_PEER_COUNTER_ADD(peer, bytes_out, len); | ||||
if (key->encrypt->cipher == OVPN_CIPHER_ALG_NONE) { | if (key->encrypt->cipher == OVPN_CIPHER_ALG_NONE) { | ||||
ret = ovpn_encap(sc, peer->peerid, m); | ret = ovpn_encap(sc, peer->peerid, m); | ||||
if (_ovpn_lock_trackerp != NULL) | if (_ovpn_lock_trackerp != NULL) | ||||
▲ Show 20 Lines • Show All 673 Lines • Show Last 20 Lines |