Ticket #15: testplugin.c

File testplugin.c, 4.7 KB (added by Emmanuel Bretelle, 11 years ago)

a plugin showing a use case of OPENVPN_PLUGIN_ACCOUNTING hook

Line 
1/**
2 * vim: tabstop=2:shiftwidth=2:softtabstop=2:expandtab
3 * Plugin demonstrating the use of
4 * https://community.openvpn.net/openvpn/ticket/15
5 *
6 * It simulates a user session where
7 *
8 * authentication occurs
9 * user bandwidth consumption is updated to accounting server regularly
10 * session close
11 *
12 * compile with
13 * gcc -shared -Wl,-soname,accounting-test.so -o \
14 * accounting-test.so testplugin.c
15 */
16
17/*
18 * server conf:
19 * plugin /path/to/accounting-test.so
20 *
21 * server need to be configured with --enable-accounting
22 * which is available in patch attached to
23 * https://community.openvpn.net/openvpn/ticket/15
24 */
25
26#include <stdio.h>
27#include <string.h>
28#include <stdlib.h>
29#include <unistd.h>
30#include <stdarg.h>
31#include <time.h>
32
33
34#include "openvpn-plugin.h"
35
36/*
37 * Our context, where we keep our state.
38 */
39
40struct plugin_context{
41  char *context;
42};
43
44char *strdupf (const char *fmt, ...);
45const char *get_env (const char *name, const char *envp[]);
46
47OPENVPN_EXPORT openvpn_plugin_handle_t
48openvpn_plugin_open_v2 (unsigned int *type_mask, const char *argv[],
49                        const char *envp[], struct openvpn_plugin_string_list **return_list)
50{
51  struct plugin_context *context;
52        int rc = 0;
53
54
55  /*
56   * Allocate our context
57   */
58  context = malloc (sizeof (struct plugin_context));
59
60  *type_mask = OPENVPN_PLUGIN_MASK ( OPENVPN_PLUGIN_CLIENT_CONNECT_V2) | 
61                OPENVPN_PLUGIN_MASK ( OPENVPN_PLUGIN_CLIENT_DISCONNECT ) |
62                OPENVPN_PLUGIN_MASK ( OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY ) |
63                OPENVPN_PLUGIN_MASK ( OPENVPN_PLUGIN_ACCOUNTING );
64  return (openvpn_plugin_handle_t) context;
65}
66
67OPENVPN_EXPORT int
68openvpn_plugin_func_v2 (openvpn_plugin_handle_t handle, const int type,
69                        const char *argv[], const char *envp[],
70                        void *per_client_context,  struct openvpn_plugin_string_list **return_list)
71{
72  struct plugin_context *context = (struct plugin_context *) handle;
73  int acc_time;
74  time_t now;
75  char *now_str;
76
77  time(&now);
78  now_str = ctime(&now);
79  if (type == OPENVPN_PLUGIN_CLIENT_CONNECT_V2){
80    acc_time = rand()%20 + 1;
81    *return_list = malloc (sizeof (struct openvpn_plugin_string_list));
82    (*return_list)->next = NULL;
83    (*return_list)->name = strdup ("config");
84    (*return_list)->value = strdupf("accounting-freq %d", acc_time);
85    printf ("ACCT %s Sending start time to accounting server %s\n", now_str, get_env("time_unix", envp));
86    printf ("ACCT %s Plugin requested accounting update in %d seconds\n", now_str, acc_time);
87    return OPENVPN_PLUGIN_FUNC_SUCCESS;
88  }
89  if (type == OPENVPN_PLUGIN_ACCOUNTING){
90      const char *tx, *rx;
91      tx = get_env("bytes_sent", envp);
92      rx = get_env("bytes_received", envp);
93      printf ("ACCT %s Sending accounting information to server %stx/%srx\n", now_str, tx ? tx : "0", rx ? rx : "0");
94      *return_list = malloc (sizeof (struct openvpn_plugin_string_list));
95      (*return_list)->next = NULL;
96      (*return_list)->name = strdup ("config");
97      acc_time = rand() % 20 + 1;
98      (*return_list)->value = strdupf("accounting-freq %d", acc_time);
99      printf("ACCT %s Acounting server requesting new update in %d seconds\n", now_str, acc_time);
100
101    return OPENVPN_PLUGIN_FUNC_SUCCESS;
102  }
103
104  if (type == OPENVPN_PLUGIN_CLIENT_DISCONNECT){
105      const char *tx, *rx;
106      tx = get_env("bytes_sent", envp);
107      rx = get_env("bytes_received", envp);
108
109    printf ("ACCT %s Sending accounting information to server %stx/%srx, session started at %s and last %s\n", 
110              now_str, tx ? tx : "0", rx ? rx : "0",
111              get_env("time_unix", envp), get_env("time_duration", envp));
112    return OPENVPN_PLUGIN_FUNC_SUCCESS;
113  }
114  if (type == OPENVPN_PLUGIN_AUTH_USER_PASS_VERIFY){
115    return OPENVPN_PLUGIN_FUNC_SUCCESS;
116  } 
117        return OPENVPN_PLUGIN_FUNC_ERROR;
118}
119
120/**
121 * plugin_close_v1:
122 * Called immediately prior to plug-in unload
123 */
124OPENVPN_EXPORT void
125openvpn_plugin_close_v1 (openvpn_plugin_handle_t handle)
126{
127  struct plugin_context *context = (struct plugin_context *) handle;
128  free (context);
129}
130
131const char *
132get_env (const char *name, const char *envp[])
133{
134  if (envp){
135    int i;
136    const int namelen = strlen (name);
137    for (i = 0; envp[i]; ++i){
138      if (!strncmp (envp[i], name, namelen))
139            {
140              const char *cp = envp[i] + namelen;
141              if (*cp == '=')
142                      return cp + 1;
143            }
144          }
145  }
146  return NULL;
147}
148
149
150
151char *
152strdupf (const char *fmt, ...){
153  va_list  vargs;
154  char     buf[BUFSIZ];
155  char    *p;
156
157  if (!fmt) {
158    return (NULL);
159  }
160  va_start (vargs, fmt);
161  vsnprintf (buf, sizeof (buf), fmt, vargs);
162  va_end (vargs);
163
164  buf[sizeof (buf) - 1] = '\0';        /* ensure buf is NUL-terminated */
165
166  if (!(p = strdup (buf))) {
167    return (NULL);
168  }
169  return (p);
170}
171
172