OpenVPN
dco_linux.c
Go to the documentation of this file.
1 /*
2  * Interface to linux dco networking code
3  *
4  * Copyright (C) 2020-2023 Antonio Quartulli <a@unstable.cc>
5  * Copyright (C) 2020-2023 Arne Schwabe <arne@rfc2549.org>
6  * Copyright (C) 2020-2023 OpenVPN Inc <sales@openvpn.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2
10  * as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program (see the file COPYING included with this
19  * distribution); if not, write to the Free Software Foundation, Inc.,
20  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  */
22 
23 
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 
28 #if defined(ENABLE_DCO) && defined(TARGET_LINUX)
29 
30 #include "syshead.h"
31 
32 #include "dco_linux.h"
33 #include "errlevel.h"
34 #include "buffer.h"
35 #include "networking.h"
36 #include "openvpn.h"
37 
38 #include "socket.h"
39 #include "tun.h"
40 #include "ssl.h"
41 #include "fdmisc.h"
42 #include "multi.h"
43 #include "ssl_verify.h"
44 
45 #include "ovpn_dco_linux.h"
46 
47 #include <netlink/socket.h>
48 #include <netlink/netlink.h>
49 #include <netlink/genl/genl.h>
50 #include <netlink/genl/family.h>
51 #include <netlink/genl/ctrl.h>
52 
53 
54 /* libnl < 3.5.0 does not set the NLA_F_NESTED on its own, therefore we
55  * have to explicitly do it to prevent the kernel from failing upon
56  * parsing of the message
57  */
58 #define nla_nest_start(_msg, _type) \
59  nla_nest_start(_msg, (_type) | NLA_F_NESTED)
60 
61 static int ovpn_get_mcast_id(dco_context_t *dco);
62 
63 void dco_check_key_ctx(const struct key_ctx_bi *key);
64 
65 typedef int (*ovpn_nl_cb)(struct nl_msg *msg, void *arg);
66 
78 static int
79 resolve_ovpn_netlink_id(int msglevel)
80 {
81  int ret;
82  struct nl_sock *nl_sock = nl_socket_alloc();
83 
84  if (!nl_sock)
85  {
86  msg(msglevel, "Allocating net link socket failed");
87  return -ENOMEM;
88  }
89 
90  ret = genl_connect(nl_sock);
91  if (ret)
92  {
93  msg(msglevel, "Cannot connect to generic netlink: %s",
94  nl_geterror(ret));
95  goto err_sock;
96  }
97  set_cloexec(nl_socket_get_fd(nl_sock));
98 
99  ret = genl_ctrl_resolve(nl_sock, OVPN_NL_NAME);
100  if (ret < 0)
101  {
102  msg(msglevel, "Cannot find ovpn_dco netlink component: %s",
103  nl_geterror(ret));
104  }
105 
106 err_sock:
107  nl_socket_free(nl_sock);
108  return ret;
109 }
110 
111 static struct nl_msg *
112 ovpn_dco_nlmsg_create(dco_context_t *dco, enum ovpn_nl_commands cmd)
113 {
114  struct nl_msg *nl_msg = nlmsg_alloc();
115  if (!nl_msg)
116  {
117  msg(M_ERR, "cannot allocate netlink message");
118  return NULL;
119  }
120 
121  genlmsg_put(nl_msg, 0, 0, dco->ovpn_dco_id, 0, 0, cmd, 0);
122  NLA_PUT_U32(nl_msg, OVPN_ATTR_IFINDEX, dco->ifindex);
123 
124  return nl_msg;
125 nla_put_failure:
126  nlmsg_free(nl_msg);
127  msg(M_INFO, "cannot put into netlink message");
128  return NULL;
129 }
130 
131 static int
132 ovpn_nl_recvmsgs(dco_context_t *dco, const char *prefix)
133 {
134  int ret = nl_recvmsgs(dco->nl_sock, dco->nl_cb);
135 
136  switch (ret)
137  {
138  case -NLE_INTR:
139  msg(M_WARN, "%s: netlink received interrupt due to signal - ignoring", prefix);
140  break;
141 
142  case -NLE_NOMEM:
143  msg(M_ERR, "%s: netlink out of memory error", prefix);
144  break;
145 
146  case -M_ERR:
147  msg(M_WARN, "%s: netlink reports blocking read - aborting wait", prefix);
148  break;
149 
150  case -NLE_NODEV:
151  msg(M_ERR, "%s: netlink reports device not found:", prefix);
152  break;
153 
154  case -NLE_OBJ_NOTFOUND:
155  msg(M_INFO, "%s: netlink reports object not found, ovpn-dco unloaded?", prefix);
156  break;
157 
158  default:
159  if (ret)
160  {
161  msg(M_NONFATAL, "%s: netlink reports error (%d): %s", prefix, ret, nl_geterror(-ret));
162  }
163  break;
164  }
165 
166  return ret;
167 }
168 
180 static int
181 ovpn_nl_msg_send(dco_context_t *dco, struct nl_msg *nl_msg, ovpn_nl_cb cb,
182  void *cb_arg, const char *prefix)
183 {
184  dco->status = 1;
185 
186  nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, cb, cb_arg);
187  nl_send_auto(dco->nl_sock, nl_msg);
188 
189  while (dco->status == 1)
190  {
191  ovpn_nl_recvmsgs(dco, prefix);
192  }
193 
194  if (dco->status < 0)
195  {
196  msg(M_INFO, "%s: failed to send netlink message: %s (%d)",
197  prefix, strerror(-dco->status), dco->status);
198  }
199 
200  return dco->status;
201 }
202 
203 struct sockaddr *
204 mapped_v4_to_v6(struct sockaddr *sock, struct gc_arena *gc)
205 {
206  struct sockaddr_in6 *sock6 = (struct sockaddr_in6 *)sock;
207  if (sock->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&sock6->sin6_addr))
208  {
209 
210  struct sockaddr_in *sock4;
211  ALLOC_OBJ_CLEAR_GC(sock4, struct sockaddr_in, gc);
212  memcpy(&sock4->sin_addr, sock6->sin6_addr.s6_addr + 12, 4);
213  sock4->sin_port = sock6->sin6_port;
214  sock4->sin_family = AF_INET;
215  return (struct sockaddr *)sock4;
216  }
217  return sock;
218 }
219 
220 int
221 dco_new_peer(dco_context_t *dco, unsigned int peerid, int sd,
222  struct sockaddr *localaddr, struct sockaddr *remoteaddr,
223  struct in_addr *remote_in4, struct in6_addr *remote_in6)
224 {
225  struct gc_arena gc = gc_new();
226  const char *remotestr = "[undefined]";
227  if (remoteaddr)
228  {
229  remotestr = print_sockaddr(remoteaddr, &gc);
230  }
231  msg(D_DCO_DEBUG, "%s: peer-id %d, fd %d, remote addr: %s", __func__,
232  peerid, sd, remotestr);
233 
234  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_NEW_PEER);
235  struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_NEW_PEER);
236  int ret = -EMSGSIZE;
237 
238  NLA_PUT_U32(nl_msg, OVPN_NEW_PEER_ATTR_PEER_ID, peerid);
239  NLA_PUT_U32(nl_msg, OVPN_NEW_PEER_ATTR_SOCKET, sd);
240 
241  /* Set the remote endpoint if defined (for UDP) */
242  if (remoteaddr)
243  {
244  remoteaddr = mapped_v4_to_v6(remoteaddr, &gc);
245  int alen = af_addr_size(remoteaddr->sa_family);
246 
247  NLA_PUT(nl_msg, OVPN_NEW_PEER_ATTR_SOCKADDR_REMOTE, alen, remoteaddr);
248  }
249 
250  if (localaddr)
251  {
252  localaddr = mapped_v4_to_v6(localaddr, &gc);
253  if (localaddr->sa_family == AF_INET)
254  {
255  NLA_PUT(nl_msg, OVPN_NEW_PEER_ATTR_LOCAL_IP, sizeof(struct in_addr),
256  &((struct sockaddr_in *)localaddr)->sin_addr);
257  }
258  else if (localaddr->sa_family == AF_INET6)
259  {
260  NLA_PUT(nl_msg, OVPN_NEW_PEER_ATTR_LOCAL_IP, sizeof(struct in6_addr),
261  &((struct sockaddr_in6 *)localaddr)->sin6_addr);
262  }
263  }
264 
265  /* Set the primary VPN IP addresses of the peer */
266  if (remote_in4)
267  {
268  NLA_PUT_U32(nl_msg, OVPN_NEW_PEER_ATTR_IPV4, remote_in4->s_addr);
269  }
270  if (remote_in6)
271  {
272  NLA_PUT(nl_msg, OVPN_NEW_PEER_ATTR_IPV6, sizeof(struct in6_addr),
273  remote_in6);
274  }
275  nla_nest_end(nl_msg, attr);
276 
277  ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
278 
279 nla_put_failure:
280  nlmsg_free(nl_msg);
281  gc_free(&gc);
282  return ret;
283 }
284 
285 static int
286 ovpn_nl_cb_finish(struct nl_msg (*msg) __attribute__ ((unused)), void *arg)
287 {
288  int *status = arg;
289 
290  *status = 0;
291  return NL_SKIP;
292 }
293 
294 /* This function is used as error callback on the netlink socket.
295  * When something goes wrong and the kernel returns an error, this function is
296  * invoked.
297  *
298  * We pass the error code to the user by means of a variable pointed by *arg
299  * (supplied by the user when setting this callback) and we parse the kernel
300  * reply to see if it contains a human-readable error. If found, it is printed.
301  */
302 static int
303 ovpn_nl_cb_error(struct sockaddr_nl (*nla) __attribute__ ((unused)),
304  struct nlmsgerr *err, void *arg)
305 {
306  struct nlmsghdr *nlh = (struct nlmsghdr *)err - 1;
307  struct nlattr *tb_msg[NLMSGERR_ATTR_MAX + 1];
308  int len = nlh->nlmsg_len;
309  struct nlattr *attrs;
310  int *ret = arg;
311  int ack_len = sizeof(*nlh) + sizeof(int) + sizeof(*nlh);
312 
313  *ret = err->error;
314 
315  if (!(nlh->nlmsg_flags & NLM_F_ACK_TLVS))
316  {
317  return NL_STOP;
318  }
319 
320  if (!(nlh->nlmsg_flags & NLM_F_CAPPED))
321  {
322  ack_len += err->msg.nlmsg_len - sizeof(*nlh);
323  }
324 
325  if (len <= ack_len)
326  {
327  return NL_STOP;
328  }
329 
330  attrs = (void *)((unsigned char *)nlh + ack_len);
331  len -= ack_len;
332 
333  nla_parse(tb_msg, NLMSGERR_ATTR_MAX, attrs, len, NULL);
334  if (tb_msg[NLMSGERR_ATTR_MSG])
335  {
336  len = strnlen((char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]),
337  nla_len(tb_msg[NLMSGERR_ATTR_MSG]));
338  msg(M_WARN, "kernel error: %*s\n", len,
339  (char *)nla_data(tb_msg[NLMSGERR_ATTR_MSG]));
340  }
341 
342  return NL_STOP;
343 }
344 
345 static void
346 ovpn_dco_init_netlink(dco_context_t *dco)
347 {
348  dco->ovpn_dco_id = resolve_ovpn_netlink_id(M_ERR);
349 
350  dco->nl_sock = nl_socket_alloc();
351 
352  if (!dco->nl_sock)
353  {
354  msg(M_ERR, "Cannot create netlink socket");
355  }
356 
357  int ret = genl_connect(dco->nl_sock);
358  if (ret)
359  {
360  msg(M_ERR, "Cannot connect to generic netlink: %s",
361  nl_geterror(ret));
362  }
363 
364  /* set close on exec and non-block on the netlink socket */
365  set_cloexec(nl_socket_get_fd(dco->nl_sock));
366  set_nonblock(nl_socket_get_fd(dco->nl_sock));
367 
368  dco->nl_cb = nl_cb_alloc(NL_CB_DEFAULT);
369  if (!dco->nl_cb)
370  {
371  msg(M_ERR, "failed to allocate netlink callback");
372  }
373 
374  nl_socket_set_cb(dco->nl_sock, dco->nl_cb);
375 
376  nl_cb_err(dco->nl_cb, NL_CB_CUSTOM, ovpn_nl_cb_error, &dco->status);
377  nl_cb_set(dco->nl_cb, NL_CB_FINISH, NL_CB_CUSTOM, ovpn_nl_cb_finish,
378  &dco->status);
379  nl_cb_set(dco->nl_cb, NL_CB_ACK, NL_CB_CUSTOM, ovpn_nl_cb_finish,
380  &dco->status);
381 
382  /* The async PACKET messages confuse libnl and it will drop them with
383  * wrong sequence numbers (NLE_SEQ_MISMATCH), so disable libnl's sequence
384  * number check */
385  nl_socket_disable_seq_check(dco->nl_sock);
386 
387  /* nl library sets the buffer size to 32k/32k by default which is sometimes
388  * overrun with very fast connecting/disconnecting clients.
389  * TODO: fix this in a better and more reliable way */
390  ASSERT(!nl_socket_set_buffer_size(dco->nl_sock, 1024*1024, 1024*1024));
391 }
392 
393 bool
394 ovpn_dco_init(int mode, dco_context_t *dco)
395 {
396  switch (mode)
397  {
398  case CM_TOP:
399  dco->ifmode = OVPN_MODE_MP;
400  break;
401 
402  case CM_P2P:
403  dco->ifmode = OVPN_MODE_P2P;
404  break;
405 
406  default:
407  ASSERT(false);
408  }
409 
410  ovpn_dco_init_netlink(dco);
411  return true;
412 }
413 
414 static void
415 ovpn_dco_uninit_netlink(dco_context_t *dco)
416 {
417  nl_socket_free(dco->nl_sock);
418  dco->nl_sock = NULL;
419 
420  /* Decrease reference count */
421  nl_cb_put(dco->nl_cb);
422 
423  CLEAR(dco);
424 }
425 
426 static void
427 ovpn_dco_register(dco_context_t *dco)
428 {
429  msg(D_DCO_DEBUG, __func__);
430  ovpn_get_mcast_id(dco);
431 
432  if (dco->ovpn_dco_mcast_id < 0)
433  {
434  msg(M_ERR, "cannot get mcast group: %s", nl_geterror(dco->ovpn_dco_mcast_id));
435  }
436 
437  /* Register for ovpn-dco specific multicast messages that the kernel may
438  * send
439  */
440  int ret = nl_socket_add_membership(dco->nl_sock, dco->ovpn_dco_mcast_id);
441  if (ret)
442  {
443  msg(M_ERR, "%s: failed to join groups: %d", __func__, ret);
444  }
445 }
446 
447 int
448 open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
449 {
450  msg(D_DCO_DEBUG, "%s: %s", __func__, dev);
451  ASSERT(tt->type == DEV_TYPE_TUN);
452 
453  int ret = net_iface_new(ctx, dev, "ovpn-dco", &tt->dco);
454  if (ret < 0)
455  {
456  msg(D_DCO_DEBUG, "Cannot create DCO interface %s: %d", dev, ret);
457  return ret;
458  }
459 
460  tt->dco.ifindex = if_nametoindex(dev);
461  if (!tt->dco.ifindex)
462  {
463  msg(M_FATAL, "DCO: cannot retrieve ifindex for interface %s", dev);
464  }
465 
466  tt->dco.dco_message_peer_id = -1;
467 
468  ovpn_dco_register(&tt->dco);
469 
470  return 0;
471 }
472 
473 void
474 close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
475 {
476  msg(D_DCO_DEBUG, __func__);
477 
478  net_iface_del(ctx, tt->actual_name);
479  ovpn_dco_uninit_netlink(&tt->dco);
480 }
481 
482 int
483 dco_swap_keys(dco_context_t *dco, unsigned int peerid)
484 {
485  msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peerid);
486 
487  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_SWAP_KEYS);
488  if (!nl_msg)
489  {
490  return -ENOMEM;
491  }
492 
493  struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_SWAP_KEYS);
494  int ret = -EMSGSIZE;
495  NLA_PUT_U32(nl_msg, OVPN_SWAP_KEYS_ATTR_PEER_ID, peerid);
496  nla_nest_end(nl_msg, attr);
497 
498  ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
499 
500 nla_put_failure:
501  nlmsg_free(nl_msg);
502  return ret;
503 }
504 
505 
506 int
507 dco_del_peer(dco_context_t *dco, unsigned int peerid)
508 {
509  msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peerid);
510 
511  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_DEL_PEER);
512  if (!nl_msg)
513  {
514  return -ENOMEM;
515  }
516 
517  struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_DEL_PEER);
518  int ret = -EMSGSIZE;
519  NLA_PUT_U32(nl_msg, OVPN_DEL_PEER_ATTR_PEER_ID, peerid);
520  nla_nest_end(nl_msg, attr);
521 
522  ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
523 
524 nla_put_failure:
525  nlmsg_free(nl_msg);
526  return ret;
527 }
528 
529 
530 int
531 dco_del_key(dco_context_t *dco, unsigned int peerid,
532  dco_key_slot_t slot)
533 {
534  msg(D_DCO_DEBUG, "%s: peer-id %d, slot %d", __func__, peerid, slot);
535 
536  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_DEL_KEY);
537  if (!nl_msg)
538  {
539  return -ENOMEM;
540  }
541 
542  struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_DEL_KEY);
543  int ret = -EMSGSIZE;
544  NLA_PUT_U32(nl_msg, OVPN_DEL_KEY_ATTR_PEER_ID, peerid);
545  NLA_PUT_U8(nl_msg, OVPN_DEL_KEY_ATTR_KEY_SLOT, slot);
546  nla_nest_end(nl_msg, attr);
547 
548  ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
549 
550 nla_put_failure:
551  nlmsg_free(nl_msg);
552  return ret;
553 }
554 
555 int
556 dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid,
557  dco_key_slot_t slot,
558  const uint8_t *encrypt_key, const uint8_t *encrypt_iv,
559  const uint8_t *decrypt_key, const uint8_t *decrypt_iv,
560  const char *ciphername)
561 {
562  msg(D_DCO_DEBUG, "%s: slot %d, key-id %d, peer-id %d, cipher %s",
563  __func__, slot, keyid, peerid, ciphername);
564 
565  const size_t key_len = cipher_kt_key_size(ciphername);
566  const int nonce_tail_len = 8;
567 
568  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_NEW_KEY);
569  if (!nl_msg)
570  {
571  return -ENOMEM;
572  }
573 
574  dco_cipher_t dco_cipher = dco_get_cipher(ciphername);
575 
576  int ret = -EMSGSIZE;
577  struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_NEW_KEY);
578  NLA_PUT_U32(nl_msg, OVPN_NEW_KEY_ATTR_PEER_ID, peerid);
579  NLA_PUT_U8(nl_msg, OVPN_NEW_KEY_ATTR_KEY_SLOT, slot);
580  NLA_PUT_U8(nl_msg, OVPN_NEW_KEY_ATTR_KEY_ID, keyid);
581  NLA_PUT_U16(nl_msg, OVPN_NEW_KEY_ATTR_CIPHER_ALG, dco_cipher);
582 
583  struct nlattr *key_enc = nla_nest_start(nl_msg,
585  if (dco_cipher != OVPN_CIPHER_ALG_NONE)
586  {
587  NLA_PUT(nl_msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, key_len, encrypt_key);
588  NLA_PUT(nl_msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, nonce_tail_len,
589  encrypt_iv);
590  }
591  nla_nest_end(nl_msg, key_enc);
592 
593  struct nlattr *key_dec = nla_nest_start(nl_msg,
595  if (dco_cipher != OVPN_CIPHER_ALG_NONE)
596  {
597  NLA_PUT(nl_msg, OVPN_KEY_DIR_ATTR_CIPHER_KEY, key_len, decrypt_key);
598  NLA_PUT(nl_msg, OVPN_KEY_DIR_ATTR_NONCE_TAIL, nonce_tail_len,
599  decrypt_iv);
600  }
601  nla_nest_end(nl_msg, key_dec);
602 
603  nla_nest_end(nl_msg, attr);
604 
605  ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
606 
607 nla_put_failure:
608  nlmsg_free(nl_msg);
609  return ret;
610 }
611 
612 int
613 dco_set_peer(dco_context_t *dco, unsigned int peerid,
614  int keepalive_interval, int keepalive_timeout, int mss)
615 {
616  msg(D_DCO_DEBUG, "%s: peer-id %d, keepalive %d/%d, mss %d", __func__,
617  peerid, keepalive_interval, keepalive_timeout, mss);
618 
619  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_SET_PEER);
620  if (!nl_msg)
621  {
622  return -ENOMEM;
623  }
624 
625  struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_SET_PEER);
626  int ret = -EMSGSIZE;
627  NLA_PUT_U32(nl_msg, OVPN_SET_PEER_ATTR_PEER_ID, peerid);
628  NLA_PUT_U32(nl_msg, OVPN_SET_PEER_ATTR_KEEPALIVE_INTERVAL,
629  keepalive_interval);
630  NLA_PUT_U32(nl_msg, OVPN_SET_PEER_ATTR_KEEPALIVE_TIMEOUT,
631  keepalive_timeout);
632  nla_nest_end(nl_msg, attr);
633 
634  ret = ovpn_nl_msg_send(dco, nl_msg, NULL, NULL, __func__);
635 
636 nla_put_failure:
637  nlmsg_free(nl_msg);
638  return ret;
639 }
640 
641 /* This function parses the reply provided by the kernel to the CTRL_CMD_GETFAMILY
642  * message. We parse the reply and we retrieve the multicast group ID associated
643  * with the "ovpn-dco" netlink family.
644  *
645  * The ID is later used to subscribe to the multicast group and be notified
646  * about any multicast message sent by the ovpn-dco kernel module.
647  */
648 static int
649 mcast_family_handler(struct nl_msg *msg, void *arg)
650 {
651  dco_context_t *dco = arg;
652  struct nlattr *tb[CTRL_ATTR_MAX + 1];
653  struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
654 
655  nla_parse(tb, CTRL_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
656  genlmsg_attrlen(gnlh, 0), NULL);
657 
658  if (!tb[CTRL_ATTR_MCAST_GROUPS])
659  {
660  return NL_SKIP;
661  }
662 
663  struct nlattr *mcgrp;
664  int rem_mcgrp;
665  nla_for_each_nested(mcgrp, tb[CTRL_ATTR_MCAST_GROUPS], rem_mcgrp)
666  {
667  struct nlattr *tb_mcgrp[CTRL_ATTR_MCAST_GRP_MAX + 1];
668 
669  nla_parse(tb_mcgrp, CTRL_ATTR_MCAST_GRP_MAX,
670  nla_data(mcgrp), nla_len(mcgrp), NULL);
671 
672  if (!tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]
673  || !tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID])
674  {
675  continue;
676  }
677 
678  if (strncmp(nla_data(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME]),
680  nla_len(tb_mcgrp[CTRL_ATTR_MCAST_GRP_NAME])) != 0)
681  {
682  continue;
683  }
684  dco->ovpn_dco_mcast_id = nla_get_u32(tb_mcgrp[CTRL_ATTR_MCAST_GRP_ID]);
685  break;
686  }
687 
688  return NL_SKIP;
689 }
695 static int
696 ovpn_get_mcast_id(dco_context_t *dco)
697 {
698  dco->ovpn_dco_mcast_id = -ENOENT;
699 
700  /* Even though 'nlctrl' is a constant, there seem to be no library
701  * provided define for it */
702  int ctrlid = genl_ctrl_resolve(dco->nl_sock, "nlctrl");
703 
704  struct nl_msg *nl_msg = nlmsg_alloc();
705  if (!nl_msg)
706  {
707  return -ENOMEM;
708  }
709 
710  genlmsg_put(nl_msg, 0, 0, ctrlid, 0, 0, CTRL_CMD_GETFAMILY, 0);
711 
712  int ret = -EMSGSIZE;
713  NLA_PUT_STRING(nl_msg, CTRL_ATTR_FAMILY_NAME, OVPN_NL_NAME);
714 
715  ret = ovpn_nl_msg_send(dco, nl_msg, mcast_family_handler, dco, __func__);
716 
717 nla_put_failure:
718  nlmsg_free(nl_msg);
719  return ret;
720 }
721 
722 /* This function parses any netlink message sent by ovpn-dco to userspace */
723 static int
724 ovpn_handle_msg(struct nl_msg *msg, void *arg)
725 {
726  dco_context_t *dco = arg;
727 
728  struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
729  struct nlattr *attrs[OVPN_ATTR_MAX + 1];
730  struct nlmsghdr *nlh = nlmsg_hdr(msg);
731 
732  if (!genlmsg_valid_hdr(nlh, 0))
733  {
734  msg(D_DCO, "ovpn-dco: invalid header");
735  return NL_SKIP;
736  }
737 
738  if (nla_parse(attrs, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
739  genlmsg_attrlen(gnlh, 0), NULL))
740  {
741  msg(D_DCO, "received bogus data from ovpn-dco");
742  return NL_SKIP;
743  }
744 
745  /* we must know which interface this message is referring to in order to
746  * avoid mixing messages for other instances
747  */
748  if (!attrs[OVPN_ATTR_IFINDEX])
749  {
750  msg(D_DCO, "ovpn-dco: Received message without ifindex");
751  return NL_SKIP;
752  }
753 
754  uint32_t ifindex = nla_get_u32(attrs[OVPN_ATTR_IFINDEX]);
755  if (ifindex != dco->ifindex)
756  {
758  "ovpn-dco: ignoring message (type=%d) for foreign ifindex %d",
759  gnlh->cmd, ifindex);
760  return NL_SKIP;
761  }
762 
763  /* based on the message type, we parse the subobject contained in the
764  * message, that stores the type-specific attributes.
765  *
766  * the "dco" object is then filled accordingly with the information
767  * retrieved from the message, so that the rest of the OpenVPN code can
768  * react as need be.
769  */
770  switch (gnlh->cmd)
771  {
772  case OVPN_CMD_DEL_PEER:
773  {
774  if (!attrs[OVPN_ATTR_DEL_PEER])
775  {
776  msg(D_DCO, "ovpn-dco: no attributes in OVPN_DEL_PEER message");
777  return NL_SKIP;
778  }
779 
780  struct nlattr *dp_attrs[OVPN_DEL_PEER_ATTR_MAX + 1];
781  if (nla_parse_nested(dp_attrs, OVPN_DEL_PEER_ATTR_MAX,
782  attrs[OVPN_ATTR_DEL_PEER], NULL))
783  {
784  msg(D_DCO, "received bogus del peer packet data from ovpn-dco");
785  return NL_SKIP;
786  }
787 
788  if (!dp_attrs[OVPN_DEL_PEER_ATTR_REASON])
789  {
790  msg(D_DCO, "ovpn-dco: no reason in DEL_PEER message");
791  return NL_SKIP;
792  }
793  if (!dp_attrs[OVPN_DEL_PEER_ATTR_PEER_ID])
794  {
795  msg(D_DCO, "ovpn-dco: no peer-id in DEL_PEER message");
796  return NL_SKIP;
797  }
798  int reason = nla_get_u8(dp_attrs[OVPN_DEL_PEER_ATTR_REASON]);
799  unsigned int peerid = nla_get_u32(dp_attrs[OVPN_DEL_PEER_ATTR_PEER_ID]);
800 
801  msg(D_DCO_DEBUG, "ovpn-dco: received CMD_DEL_PEER, ifindex: %d, peer-id %d, reason: %d",
802  ifindex, peerid, reason);
803  dco->dco_message_peer_id = peerid;
804  dco->dco_del_peer_reason = reason;
805  dco->dco_message_type = OVPN_CMD_DEL_PEER;
806 
807  break;
808  }
809 
810  default:
811  msg(D_DCO, "ovpn-dco: received unknown command: %d", gnlh->cmd);
812  dco->dco_message_type = 0;
813  return NL_SKIP;
814  }
815 
816  return NL_OK;
817 }
818 
819 int
821 {
822  msg(D_DCO_DEBUG, __func__);
823  nl_cb_set(dco->nl_cb, NL_CB_VALID, NL_CB_CUSTOM, ovpn_handle_msg, dco);
824 
825  return ovpn_nl_recvmsgs(dco, __func__);
826 }
827 
828 static void
829 dco_update_peer_stat(struct context_2 *c2, struct nlattr *tb[], uint32_t id)
830 {
832  {
834  msg(D_DCO_DEBUG, "%s / dco_read_bytes: " counter_format, __func__,
835  c2->dco_read_bytes);
836  }
837  else
838  {
839  msg(M_WARN, "%s: no link RX bytes provided in reply for peer %u",
840  __func__, id);
841  }
842 
844  {
846  msg(D_DCO_DEBUG, "%s / dco_write_bytes: " counter_format, __func__,
847  c2->dco_write_bytes);
848  }
849  else
850  {
851  msg(M_WARN, "%s: no link TX bytes provided in reply for peer %u",
852  __func__, id);
853  }
854 
856  {
858  msg(D_DCO_DEBUG, "%s / tun_read_bytes: " counter_format, __func__,
859  c2->tun_read_bytes);
860  }
861  else
862  {
863  msg(M_WARN, "%s: no VPN RX bytes provided in reply for peer %u",
864  __func__, id);
865  }
866 
868  {
870  msg(D_DCO_DEBUG, "%s / tun_write_bytes: " counter_format, __func__,
871  c2->tun_write_bytes);
872  }
873  else
874  {
875  msg(M_WARN, "%s: no VPN TX bytes provided in reply for peer %u",
876  __func__, id);
877  }
878 }
879 
880 int
881 dco_parse_peer_multi(struct nl_msg *msg, void *arg)
882 {
883  struct nlattr *tb[OVPN_ATTR_MAX + 1];
884  struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
885 
886  msg(D_DCO_DEBUG, "%s: parsing message...", __func__);
887 
888  nla_parse(tb, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
889  genlmsg_attrlen(gnlh, 0), NULL);
890 
891  if (!tb[OVPN_ATTR_GET_PEER])
892  {
893  return NL_SKIP;
894  }
895 
896  struct nlattr *tb_peer[OVPN_GET_PEER_RESP_ATTR_MAX + 1];
897 
898  nla_parse(tb_peer, OVPN_GET_PEER_RESP_ATTR_MAX,
899  nla_data(tb[OVPN_ATTR_GET_PEER]),
900  nla_len(tb[OVPN_ATTR_GET_PEER]), NULL);
901 
902  if (!tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID])
903  {
904  msg(M_WARN, "%s: no peer-id provided in reply", __func__);
905  return NL_SKIP;
906  }
907 
908  struct multi_context *m = arg;
909  uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]);
910 
911  if (peer_id >= m->max_clients || !m->instances[peer_id])
912  {
913  msg(M_WARN, "%s: cannot store DCO stats for peer %u", __func__,
914  peer_id);
915  return NL_SKIP;
916  }
917 
918  dco_update_peer_stat(&m->instances[peer_id]->context.c2, tb_peer, peer_id);
919 
920  return NL_OK;
921 }
922 
923 int
925 {
926  msg(D_DCO_DEBUG, "%s", __func__);
927 
928  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_GET_PEER);
929 
930  nlmsg_hdr(nl_msg)->nlmsg_flags |= NLM_F_DUMP;
931 
932  int ret = ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer_multi, m, __func__);
933 
934  nlmsg_free(nl_msg);
935  return ret;
936 }
937 
938 static int
939 dco_parse_peer(struct nl_msg *msg, void *arg)
940 {
941  struct context *c = arg;
942  struct nlattr *tb[OVPN_ATTR_MAX + 1];
943  struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
944 
945  msg(D_DCO_DEBUG, "%s: parsing message...", __func__);
946 
947  nla_parse(tb, OVPN_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
948  genlmsg_attrlen(gnlh, 0), NULL);
949 
950  if (!tb[OVPN_ATTR_GET_PEER])
951  {
952  msg(D_DCO_DEBUG, "%s: malformed reply", __func__);
953  return NL_SKIP;
954  }
955 
956  struct nlattr *tb_peer[OVPN_GET_PEER_RESP_ATTR_MAX + 1];
957 
958  nla_parse(tb_peer, OVPN_GET_PEER_RESP_ATTR_MAX,
959  nla_data(tb[OVPN_ATTR_GET_PEER]),
960  nla_len(tb[OVPN_ATTR_GET_PEER]), NULL);
961 
962  if (!tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID])
963  {
964  msg(M_WARN, "%s: no peer-id provided in reply", __func__);
965  return NL_SKIP;
966  }
967 
968  uint32_t peer_id = nla_get_u32(tb_peer[OVPN_GET_PEER_RESP_ATTR_PEER_ID]);
969  if (c->c2.tls_multi->dco_peer_id != peer_id)
970  {
971  return NL_SKIP;
972  }
973 
974  dco_update_peer_stat(&c->c2, tb_peer, peer_id);
975 
976  return NL_OK;
977 }
978 
979 int
980 dco_get_peer_stats(struct context *c)
981 {
982  uint32_t peer_id = c->c2.tls_multi->dco_peer_id;
983  msg(D_DCO_DEBUG, "%s: peer-id %d", __func__, peer_id);
984 
985  if (!c->c1.tuntap)
986  {
987  return 0;
988  }
989 
990  dco_context_t *dco = &c->c1.tuntap->dco;
991  struct nl_msg *nl_msg = ovpn_dco_nlmsg_create(dco, OVPN_CMD_GET_PEER);
992  struct nlattr *attr = nla_nest_start(nl_msg, OVPN_ATTR_GET_PEER);
993  int ret = -EMSGSIZE;
994 
995  NLA_PUT_U32(nl_msg, OVPN_GET_PEER_ATTR_PEER_ID, peer_id);
996  nla_nest_end(nl_msg, attr);
997 
998  ret = ovpn_nl_msg_send(dco, nl_msg, dco_parse_peer, c, __func__);
999 
1000 nla_put_failure:
1001  nlmsg_free(nl_msg);
1002  return ret;
1003 }
1004 
1005 bool
1006 dco_available(int msglevel)
1007 {
1008  if (resolve_ovpn_netlink_id(D_DCO_DEBUG) < 0)
1009  {
1010  msg(msglevel,
1011  "Note: Kernel support for ovpn-dco missing, disabling data channel offload.");
1012  return false;
1013  }
1014 
1015  return true;
1016 }
1017 
1018 const char *
1019 dco_version_string(struct gc_arena *gc)
1020 {
1021  struct buffer out = alloc_buf_gc(256, gc);
1022  FILE *fp = fopen("/sys/module/ovpn_dco_v2/version", "r");
1023  if (!fp)
1024  {
1025  return "N/A";
1026  }
1027 
1028  if (!fgets(BSTR(&out), BCAP(&out), fp))
1029  {
1030  fclose(fp);
1031  return "ERR";
1032  }
1033 
1034  /* remove potential newline at the end of the string */
1035  char *str = BSTR(&out);
1036  char *nl = strchr(str, '\n');
1037  if (nl)
1038  {
1039  *nl = '\0';
1040  }
1041 
1042  fclose(fp);
1043  return BSTR(&out);
1044 }
1045 
1046 void
1047 dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
1048 {
1049  if (dco && dco->nl_sock)
1050  {
1051  event_ctl(es, nl_socket_get_fd(dco->nl_sock), EVENT_READ, arg);
1052  }
1053 }
1054 
1055 const char *
1057 {
1058  return "AES-128-GCM:AES-256-GCM:AES-192-GCM:CHACHA20-POLY1305";
1059 }
1060 
1061 #endif /* defined(ENABLE_DCO) && defined(TARGET_LINUX) */
OVPN_ATTR_IFINDEX
@ OVPN_ATTR_IFINDEX
Definition: ovpn_dco_linux.h:88
OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_VPN_RX_BYTES
Definition: ovpn_dco_linux.h:191
OVPN_CMD_SET_PEER
@ OVPN_CMD_SET_PEER
@OVPN_CMD_SET_PEER: Tweak parameters for an existing peer
Definition: ovpn_dco_linux.h:35
OVPN_CMD_DEL_PEER
@ OVPN_CMD_DEL_PEER
@OVPN_CMD_DEL_PEER: Remove peer from internal table
Definition: ovpn_dco_linux.h:40
D_DCO_DEBUG
#define D_DCO_DEBUG
Definition: errlevel.h:118
M_INFO
#define M_INFO
Definition: errlevel.h:55
OVPN_NEW_KEY_ATTR_KEY_ID
@ OVPN_NEW_KEY_ATTR_KEY_ID
Definition: ovpn_dco_linux.h:114
dco_new_key
int dco_new_key(dco_context_t *dco, unsigned int peerid, int keyid, dco_key_slot_t slot, const uint8_t *encrypt_key, const uint8_t *encrypt_iv, const uint8_t *decrypt_key, const uint8_t *decrypt_iv, const char *ciphername)
Definition: dco_win.c:295
OVPN_SET_PEER_ATTR_KEEPALIVE_INTERVAL
@ OVPN_SET_PEER_ATTR_KEEPALIVE_INTERVAL
Definition: ovpn_dco_linux.h:157
gc_new
static struct gc_arena gc_new(void)
Definition: buffer.h:1031
dco_get_supported_ciphers
const char * dco_get_supported_ciphers()
Definition: dco_win.c:469
DEV_TYPE_TUN
#define DEV_TYPE_TUN
Definition: proto.h:37
OVPN_GET_PEER_ATTR_PEER_ID
@ OVPN_GET_PEER_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:175
context_2::tls_multi
struct tls_multi * tls_multi
TLS state structure for this VPN tunnel.
Definition: openvpn.h:326
print_sockaddr
static const char * print_sockaddr(const struct sockaddr *addr, struct gc_arena *gc)
Definition: socket.h:371
networking.h
OVPN_NEW_PEER_ATTR_SOCKADDR_REMOTE
@ OVPN_NEW_PEER_ATTR_SOCKADDR_REMOTE
Definition: ovpn_dco_linux.h:144
M_FATAL
#define M_FATAL
Definition: error.h:95
context_1::tuntap
struct tuntap * tuntap
Tun/tap virtual network interface.
Definition: openvpn.h:170
dco_version_string
const char * dco_version_string(struct gc_arena *gc)
Definition: dco_win.c:387
OVPN_CIPHER_ALG_NONE
@ OVPN_CIPHER_ALG_NONE
Definition: ovpn_dco_freebsd.h:53
OVPN_GET_PEER_RESP_ATTR_MAX
@ OVPN_GET_PEER_RESP_ATTR_MAX
Definition: ovpn_dco_linux.h:201
M_NONFATAL
#define M_NONFATAL
Definition: error.h:96
context
Contains all state information for one tunnel.
Definition: openvpn.h:476
es
struct env_set * es
Definition: test_pkcs11.c:133
BSTR
#define BSTR(buf)
Definition: buffer.h:129
context_2::tun_read_bytes
counter_type tun_read_bytes
Definition: openvpn.h:267
tuntap::type
int type
Definition: tun.h:174
alloc_buf_gc
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition: buffer.c:88
OVPN_SET_PEER_ATTR_PEER_ID
@ OVPN_SET_PEER_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:156
OVPN_ATTR_SWAP_KEYS
@ OVPN_ATTR_SWAP_KEYS
Definition: ovpn_dco_linux.h:93
open_tun_dco
int open_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx, const char *dev)
Definition: dco_win.c:62
openvpn.h
OVPN_CMD_NEW_PEER
@ OVPN_CMD_NEW_PEER
@OVPN_CMD_NEW_PEER: Configure peer with its crypto keys
Definition: ovpn_dco_linux.h:30
OVPN_DEL_PEER_ATTR_MAX
@ OVPN_DEL_PEER_ATTR_MAX
Definition: ovpn_dco_linux.h:170
ovpn_dco_linux.h
OVPN_NL_NAME
#define OVPN_NL_NAME
Definition: ovpn_dco_linux.h:14
fdmisc.h
close_tun_dco
static void close_tun_dco(struct tuntap *tt, openvpn_net_ctx_t *ctx)
Definition: dco.h:299
OVPN_MODE_MP
@ OVPN_MODE_MP
Definition: ovpn_dco_linux.h:251
openvpn_net_ctx_t
void * openvpn_net_ctx_t
Definition: networking.h:28
dco_get_peer_stats
int dco_get_peer_stats(struct context *c)
Definition: dco_win.c:433
EVENT_READ
#define EVENT_READ
Definition: event.h:39
OVPN_NEW_KEY_ATTR_CIPHER_ALG
@ OVPN_NEW_KEY_ATTR_CIPHER_ALG
Definition: ovpn_dco_linux.h:115
dco_new_peer
int dco_new_peer(dco_context_t *dco, unsigned int peerid, int sd, struct sockaddr *localaddr, struct sockaddr *remoteaddr, struct in_addr *remote_in4, struct in6_addr *remote_in6)
Definition: dco_win.c:248
OVPN_CMD_NEW_KEY
@ OVPN_CMD_NEW_KEY
Definition: ovpn_dco_linux.h:42
dco_do_read
int dco_do_read(dco_context_t *dco)
Definition: dco_win.c:418
OVPN_NEW_KEY_ATTR_PEER_ID
@ OVPN_NEW_KEY_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:112
OVPN_ATTR_SET_PEER
@ OVPN_ATTR_SET_PEER
Definition: ovpn_dco_linux.h:90
key
Container for unidirectional cipher and HMAC key material.
Definition: crypto.h:149
multi_context::max_clients
int max_clients
Definition: multi.h:179
OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_LINK_RX_BYTES
Definition: ovpn_dco_linux.h:195
tuntap::actual_name
char * actual_name
Definition: tun.h:186
CLEAR
#define CLEAR(x)
Definition: basic.h:33
OVPN_DEL_KEY_ATTR_KEY_SLOT
@ OVPN_DEL_KEY_ATTR_KEY_SLOT
Definition: ovpn_dco_linux.h:126
event_ctl
static void event_ctl(struct event_set *es, event_t event, unsigned int rwflags, void *arg)
Definition: event.h:160
context::c2
struct context_2 c2
Level 2 context.
Definition: openvpn.h:517
key_ctx_bi
Container for two sets of OpenSSL cipher and/or HMAC contexts for both sending and receiving directio...
Definition: crypto.h:217
multi_context::instances
struct multi_instance ** instances
Array of multi_instances.
Definition: multi.h:156
ssl_verify.h
ASSERT
#define ASSERT(x)
Definition: error.h:201
D_DCO
#define D_DCO
Definition: errlevel.h:94
tun.h
OVPN_KEY_DIR_ATTR_CIPHER_KEY
@ OVPN_KEY_DIR_ATTR_CIPHER_KEY
Definition: ovpn_dco_linux.h:103
OVPN_CMD_GET_PEER
@ OVPN_CMD_GET_PEER
@OVPN_CMD_GET_PEER: Retrieve the status of a peer or all peers
Definition: ovpn_dco_linux.h:51
ovpn_dco_init
bool ovpn_dco_init(int mode, dco_context_t *dco)
Definition: dco_win.c:56
context_2::dco_write_bytes
counter_type dco_write_bytes
Definition: openvpn.h:273
M_WARN
#define M_WARN
Definition: error.h:97
OVPN_MODE_P2P
@ OVPN_MODE_P2P
Definition: ovpn_dco_linux.h:250
ALLOC_OBJ_CLEAR_GC
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition: buffer.h:1103
dco_event_set
void dco_event_set(dco_context_t *dco, struct event_set *es, void *arg)
Definition: dco_win.c:462
tls_multi::dco_peer_id
int dco_peer_id
This is the handle that DCO uses to identify this session with the kernel.
Definition: ssl_common.h:687
dco_linux.h
multi.h
M_ERR
#define M_ERR
Definition: error.h:111
dco_context_t
void * dco_context_t
Definition: dco.h:254
errlevel.h
set_nonblock
void set_nonblock(socket_descriptor_t fd)
Definition: fdmisc.c:69
dco_available
bool dco_available(int msglevel)
Definition: dco_win.c:360
OVPN_NEW_KEY_ATTR_KEY_SLOT
@ OVPN_NEW_KEY_ATTR_KEY_SLOT
Definition: ovpn_dco_linux.h:113
OVPN_NEW_PEER_ATTR_IPV4
@ OVPN_NEW_PEER_ATTR_IPV4
Definition: ovpn_dco_linux.h:146
context_2::tun_write_bytes
counter_type tun_write_bytes
Definition: openvpn.h:268
buffer
Wrapper structure for dynamically allocated memory.
Definition: buffer.h:60
dco_set_peer
int dco_set_peer(dco_context_t *dco, unsigned int peerid, int keepalive_interval, int keepalive_timeout, int mss)
Definition: dco_win.c:272
OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_VPN_TX_BYTES
Definition: ovpn_dco_linux.h:192
BCAP
#define BCAP(buf)
Definition: buffer.h:130
ssl.h
OVPN_ATTR_DEL_KEY
@ OVPN_ATTR_DEL_KEY
Definition: ovpn_dco_linux.h:94
OVPN_NEW_PEER_ATTR_PEER_ID
@ OVPN_NEW_PEER_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:143
buffer.h
syshead.h
OVPN_DEL_KEY_ATTR_PEER_ID
@ OVPN_DEL_KEY_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:125
OVPN_ATTR_GET_PEER
@ OVPN_ATTR_GET_PEER
Definition: ovpn_dco_linux.h:95
gc_arena
Garbage collection arena used to keep track of dynamically allocated memory.
Definition: buffer.h:116
OVPN_DEL_PEER_ATTR_REASON
@ OVPN_DEL_PEER_ATTR_REASON
Definition: ovpn_dco_linux.h:166
dco_del_peer
int dco_del_peer(dco_context_t *dco, unsigned int peerid)
Definition: dco_win.c:257
OVPN_GET_PEER_RESP_ATTR_PEER_ID
@ OVPN_GET_PEER_RESP_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:183
OVPN_KEY_DIR_ATTR_NONCE_TAIL
@ OVPN_KEY_DIR_ATTR_NONCE_TAIL
Definition: ovpn_dco_linux.h:104
multi_context
Main OpenVPN server state structure.
Definition: multi.h:155
cipher_kt_key_size
int cipher_kt_key_size(const char *ciphername)
Returns the size of keys used by the cipher, in bytes.
Definition: crypto_openssl.c:658
counter_format
#define counter_format
Definition: common.h:31
OVPN_ATTR_MAX
@ OVPN_ATTR_MAX
Definition: ovpn_dco_linux.h:98
set_cloexec
void set_cloexec(socket_descriptor_t fd)
Definition: fdmisc.c:79
event_set
Definition: event.h:124
OVPN_ATTR_NEW_KEY
@ OVPN_ATTR_NEW_KEY
Definition: ovpn_dco_linux.h:92
dco_del_key
int dco_del_key(dco_context_t *dco, unsigned int peerid, dco_key_slot_t slot)
Definition: dco_win.c:336
dco_swap_keys
int dco_swap_keys(dco_context_t *dco, unsigned int peer_id)
Definition: dco_win.c:345
OVPN_NEW_KEY_ATTR_DECRYPT_KEY
@ OVPN_NEW_KEY_ATTR_DECRYPT_KEY
Definition: ovpn_dco_linux.h:117
tuntap::dco
dco_context_t dco
Definition: tun.h:234
CM_TOP
#define CM_TOP
Definition: openvpn.h:486
context_2::dco_read_bytes
counter_type dco_read_bytes
Definition: openvpn.h:270
OVPN_NEW_PEER_ATTR_SOCKET
@ OVPN_NEW_PEER_ATTR_SOCKET
Definition: ovpn_dco_linux.h:145
status
static SERVICE_STATUS status
Definition: interactive.c:52
OVPN_NL_MULTICAST_GROUP_PEERS
#define OVPN_NL_MULTICAST_GROUP_PEERS
Definition: ovpn_dco_linux.h:16
gc_free
static void gc_free(struct gc_arena *a)
Definition: buffer.h:1039
ovpn_nl_commands
ovpn_nl_commands
enum ovpn_nl_commands - supported netlink commands
Definition: ovpn_dco_linux.h:21
tuntap
Definition: tun.h:171
OVPN_NEW_KEY_ATTR_ENCRYPT_KEY
@ OVPN_NEW_KEY_ATTR_ENCRYPT_KEY
Definition: ovpn_dco_linux.h:116
socket.h
__attribute__
__attribute__((unused))
Definition: test.c:42
config.h
OVPN_CMD_DEL_KEY
@ OVPN_CMD_DEL_KEY
Definition: ovpn_dco_linux.h:46
OVPN_SWAP_KEYS_ATTR_PEER_ID
@ OVPN_SWAP_KEYS_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:134
OVPN_NEW_PEER_ATTR_IPV6
@ OVPN_NEW_PEER_ATTR_IPV6
Definition: ovpn_dco_linux.h:147
OVPN_SET_PEER_ATTR_KEEPALIVE_TIMEOUT
@ OVPN_SET_PEER_ATTR_KEEPALIVE_TIMEOUT
Definition: ovpn_dco_linux.h:158
OVPN_CMD_SWAP_KEYS
@ OVPN_CMD_SWAP_KEYS
Definition: ovpn_dco_linux.h:44
dco_get_peer_stats_multi
int dco_get_peer_stats_multi(dco_context_t *dco, struct multi_context *m)
Definition: dco_win.c:426
context_2
Level 2 context containing state that is reset on both SIGHUP and SIGUSR1 restarts.
Definition: openvpn.h:226
OVPN_ATTR_DEL_PEER
@ OVPN_ATTR_DEL_PEER
Definition: ovpn_dco_linux.h:91
OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES
@ OVPN_GET_PEER_RESP_ATTR_LINK_TX_BYTES
Definition: ovpn_dco_linux.h:196
af_addr_size
static int af_addr_size(sa_family_t af)
Definition: socket.h:867
OVPN_ATTR_NEW_PEER
@ OVPN_ATTR_NEW_PEER
Definition: ovpn_dco_linux.h:89
msg
#define msg(flags,...)
Definition: error.h:150
OVPN_NEW_PEER_ATTR_LOCAL_IP
@ OVPN_NEW_PEER_ATTR_LOCAL_IP
Definition: ovpn_dco_linux.h:148
OVPN_DEL_PEER_ATTR_PEER_ID
@ OVPN_DEL_PEER_ATTR_PEER_ID
Definition: ovpn_dco_linux.h:167
multi_instance::context
struct context context
The context structure storing state for this VPN tunnel.
Definition: multi.h:136
context::c1
struct context_1 c1
Level 1 context.
Definition: openvpn.h:516
CM_P2P
#define CM_P2P
Definition: openvpn.h:485