drivers/net/ovpn/tcp.c
Source file repositories/reference/linux-study-clean/drivers/net/ovpn/tcp.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/net/ovpn/tcp.c- Extension
.c- Size
- 16373 bytes
- Lines
- 661
- Domain
- Driver Families
- Bucket
- drivers/net
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Uses kernel synchronization; read lock ordering, sleepability, and interrupt context assumptions before translating.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/skbuff.hnet/hotdata.hnet/inet_common.hnet/ipv6.hnet/tcp.hnet/transp_v6.hnet/route.htrace/events/sock.hovpnpriv.hmain.hio.hpeer.hproto.hskb.htcp.h
Detected Declarations
function ovpn_tcp_parsefunction ovpn_tcp_to_userspacefunction ovpn_tcp_rcvfunction ovpn_tcp_recvmsgfunction ovpn_tcp_socket_detachfunction ovpn_tcp_socket_wait_finishfunction ovpn_tcp_send_sockfunction ovpn_tcp_tx_workfunction ovpn_tcp_send_sock_skbfunction ovpn_tcp_send_skbfunction ovpn_tcp_releasefunction ovpn_tcp_sendmsgfunction ovpn_tcp_disconnectfunction ovpn_tcp_data_readyfunction ovpn_tcp_write_spacefunction ovpn_tcp_peer_del_workfunction ovpn_tcp_socket_attachfunction ovpn_tcp_closefunction ovpn_tcp_pollfunction ovpn_tcp_build_protosfunction ovpn_tcp_init
Annotated Snippet
static struct proto_ops ovpn_tcp_ops __ro_after_init;
static struct proto ovpn_tcp6_prot __ro_after_init;
static struct proto_ops ovpn_tcp6_ops __ro_after_init;
static int ovpn_tcp_parse(struct strparser *strp, struct sk_buff *skb)
{
struct strp_msg *rxm = strp_msg(skb);
__be16 blen;
u16 len;
int err;
/* when packets are written to the TCP stream, they are prepended with
* two bytes indicating the actual packet size.
* Parse accordingly and return the actual size (including the size
* header)
*/
if (skb->len < rxm->offset + 2)
return 0;
err = skb_copy_bits(skb, rxm->offset, &blen, sizeof(blen));
if (err < 0)
return err;
len = be16_to_cpu(blen);
if (len < 2)
return -EINVAL;
return len + 2;
}
/* queue skb for sending to userspace via recvmsg on the socket */
static void ovpn_tcp_to_userspace(struct ovpn_peer *peer, struct sock *sk,
struct sk_buff *skb)
{
skb_set_owner_r(skb, sk);
memset(skb->cb, 0, sizeof(skb->cb));
skb_queue_tail(&peer->tcp.user_queue, skb);
peer->tcp.sk_cb.sk_data_ready(sk);
}
static struct sk_buff *ovpn_tcp_skb_packet(const struct ovpn_peer *peer,
struct sk_buff *orig_skb,
const int pkt_len, const int pkt_off)
{
struct sk_buff *ovpn_skb;
int err;
/* create a new skb with only the content of the current packet */
ovpn_skb = netdev_alloc_skb(peer->ovpn->dev, pkt_len);
if (unlikely(!ovpn_skb))
goto err;
skb_copy_header(ovpn_skb, orig_skb);
err = skb_copy_bits(orig_skb, pkt_off, skb_put(ovpn_skb, pkt_len),
pkt_len);
if (unlikely(err)) {
net_warn_ratelimited("%s: skb_copy_bits failed for peer %u\n",
netdev_name(peer->ovpn->dev), peer->id);
kfree_skb(ovpn_skb);
goto err;
}
consume_skb(orig_skb);
return ovpn_skb;
err:
kfree_skb(orig_skb);
return NULL;
}
static void ovpn_tcp_rcv(struct strparser *strp, struct sk_buff *skb)
{
struct ovpn_peer *peer = container_of(strp, struct ovpn_peer, tcp.strp);
struct strp_msg *msg = strp_msg(skb);
int pkt_len = msg->full_len - 2;
u8 opcode;
/* we need at least 4 bytes of data in the packet
* to extract the opcode and the key ID later on
*/
if (unlikely(pkt_len < OVPN_OPCODE_SIZE)) {
net_warn_ratelimited("%s: packet too small to fetch opcode for peer %u\n",
netdev_name(peer->ovpn->dev), peer->id);
goto err;
}
/* extract the packet into a new skb */
skb = ovpn_tcp_skb_packet(peer, skb, pkt_len, msg->offset + 2);
if (unlikely(!skb))
goto err;
Annotation
- Immediate include surface: `linux/skbuff.h`, `net/hotdata.h`, `net/inet_common.h`, `net/ipv6.h`, `net/tcp.h`, `net/transp_v6.h`, `net/route.h`, `trace/events/sock.h`.
- Detected declarations: `function ovpn_tcp_parse`, `function ovpn_tcp_to_userspace`, `function ovpn_tcp_rcv`, `function ovpn_tcp_recvmsg`, `function ovpn_tcp_socket_detach`, `function ovpn_tcp_socket_wait_finish`, `function ovpn_tcp_send_sock`, `function ovpn_tcp_tx_work`, `function ovpn_tcp_send_sock_skb`, `function ovpn_tcp_send_skb`.
- Atlas domain: Driver Families / drivers/net.
- Implementation status: pattern implementation candidate.
- Synchronization appears in or near this file; preserve lock ordering, sleepability, and interrupt-context constraints.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.