AnyConnect Secure Mobility Client  5.1.14.145
ClientIfcBase.h
1 /**************************************************************************
2 * Copyright (c) 2006, 2021-2025 Cisco Systems, Inc.
3 * All Rights Reserved. Cisco Highly Confidential.
4 ***************************************************************************
5 *
6 * File: ClientIfcBase.h
7 * Author: Chris Fitzgerald
8 * Date: 08/2007
9 *
10 ***************************************************************************
11 * Client Interface Base class implementation for the Client API.
12 ***************************************************************************/
13 
14 #ifndef _CLIENTIFCBASE_
15 #define _CLIENTIFCBASE_
16 
17 #include <list>
18 #include <vector>
19 #include <memory>
20 
21 #include "ClientIfcCommon.h"
22 #include "api.h"
23 
24 #if defined(ANYCONNECT_USE_SNAK)
25 #include "SNAK_CertPlugin.h"
26 #endif
27 
28 #if defined(HOST_DATA_SUPPORTED)
29 class IHostData;
30 #endif
31 
32 class ConnectPromptInfo;
33 class MsgWithArg;
34 class VPNStats;
35 class PreferenceInfo;
36 class ProxyIfc;
37 class CIpcMessage;
38 class CertObj;
39 class HostEntry;
40 class ClientIfcInternal;
41 
42 #if defined(VPNAPI_TRANSMIGRATION_SUPPORTED)
43 class CSharedAccessLock;
44 #endif
45 
46 #if defined(VPNAPI_EVENT_NOTIFICATION_SUPPORTED)
47 class CEventNotificationTlv;
48 #endif
49 
50 #if defined(CREDENTIAL_PREFILL_SUPPORTED)
51 class CredentialPrefill;
52 #endif
53 
54 #if (defined(ANYCONNECT_USE_SNAK) || defined(PLATFORM_APPLE_SSLVPN)) && !defined(PLATFORM_WIN_APP)
55 class ManagedCertificate;
56 #endif
57 
58 #if defined(PROGRAM_DATA_IMPORT_SUPPORTED)
59 class IACImporterAsync;
60 class IACImporterAsyncCB;
61 #endif
62 
63 class VPN_VPNAPI ClientIfcBase
64 {
65  friend class EventMgr;
66  friend class ClientIfcInternal;
67 
68 protected:
69 
70  ClientIfcBase();
71  virtual ~ClientIfcBase();
72 
73  /**
74  * Callback used to deliver new statistics related to the VPN
75  * connection.
76  *
77  * When a connection is active, a new set of statistics is
78  * delivered each second.
79  *
80  * @see resetStats(), stopStats() and startStats()
81  *
82  */
83  virtual void StatsCB(VPNStats &stats) = 0;
84 
85 
86  /**
87  * Callback used to deliver VPN state and state change string.
88  * The stateString delivered by this method is localized.
89  *
90  * See the ::VPNState enum found in api.h for set of valid states.
91  */
92  virtual void StateCB(const VPNState state,
93  const VPNSubState subState,
94  const tstring stateString) = 0;
95 
96 
97  /**
98  * If a banner needs to be acknowledged, this CB delivers the banner
99  * to the client.
100  *
101  * NOTE: Connection establishment will block until the method
102  * setBannerResponse() is called.
103  *
104  * In a GUI, a banner would typically be displayed in a modal dialog
105  * with an accept or decline button selection.
106  *
107  * @see setBannerResponse() to set the user response to the banner.
108  */
109  virtual void BannerCB(const tstring &banner) = 0;
110 
111  /**
112  * If a pre-connect reminder needs to be acknowledged, this CB delivers
113  * the pre-connect reminder to the client.
114  *
115  * NOTE: Connection establishment will block until the method
116  * setPreConnectReminderResponse() is called.
117  *
118  * In a GUI, a pre-connect reminder would typically be displayed in a modal
119  * dialog with an OK button selection.
120  *
121  * @see setPreConnectReminderResponse() to set the user acknowledgement to
122  * the pre-connect reminder message.
123  */
124  virtual void PreConnectReminderCB(const tstring &rtstrPreConnectReminder);
125 
126  /**
127  * Messages are delivered via the NoticeCB and can come from multiple
128  * sources. There are four message types (error, warning, info and
129  * status). See the ::MessageType enum in api.h for the list.
130  *
131  * Clients using the API as an embedded application (not
132  * user visible) might want to further characterize
133  * messages. One option here is to use the AnyConnect message
134  * catalog and assign message codes as the translations for
135  * various messages. An application could then track messages based
136  * on its own error code scheme.
137  */
138  virtual void NoticeCB(const tstring &notice,
139  const MessageType type,
140  const bool bSensitive = false) = 0;
141 
142 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID) || defined(PLATFORM_CHROMEBOOK)
143  virtual void CertBannerCB(const tstring &certBannerSummary,
144  const uint32_t nCertBannerCertLen,
145  const uint8_t *pCertBannerCertDer,
146  const std::list<tstring> &confirmReasons,
147  const std::list<CertConfirmReason> &confirmReasonEnums,
148  bool bImportAllowed = true) = 0;
149 #endif
150 
151  /**
152  * This CB would likely occur only during a connection when it was
153  * detected that the software needed to be upgraded, or when Start
154  * Before Logon (SBL) is being used.
155  *
156  * Unlike the other callback methods, this method provides a default
157  * implementation (calling the system's exit() function).
158  * If clients of the API wish to override this behavior, they are
159  * responsible for ensuring that the current running process exits with
160  * the return code specified by returnCode.
161  *
162  * <b>Caution</b>: IF YOU OVERRIDE THIS METHOD AND DO NOT EXIT WITH
163  * THE PROPER CODE SOFTWARE UPDATE FUNCTIONALITY IN YOUR CLIENT WILL
164  * BREAK
165  */
166  virtual void ExitNoticeCB(const tstring &tstrNotice,
167  const int returnCode);
168 
169 
170  /**
171  * Under normal operating conditions, this CB is called as soon
172  * as the attach method completes. In case the service (vpn agent)
173  * is not ready, this CB is not called until it is.
174  *
175  * Any API calls made prior to this CB being called will result in a
176  * NoticeCB error message.
177  */
178  virtual void ServiceReadyCB() = 0;
179 
180 
181 
182  /**
183  * This method supports prompting for single or multiple values. All
184  * prompts are considered mandatory.
185  *
186  * The ConnectPromptInfo object contains a list of PromptEntry
187  * instances. The labels and their default values (if any) can be
188  * found in these instances. After the data has been collected from the user
189  * it can be set into these same instances. When ready, the client
190  * application should call the method UserSubmit() to have the
191  * responses read by the API.
192  */
193  virtual void UserPromptCB(ConnectPromptInfo &ConnectPrompt) = 0;
194 
195 
196  /**
197  * Use this method to provide Window Manager hints to GUI
198  * applications. To receive these hints, the application must
199  * identify itself as a GUI in the attach method. In addition, this
200  * method should be overridden to receive any generated events.
201  *
202  * Event that can be received include those indicating that a user is
203  * starting a second instance of the GUI application. This information
204  * can be used to tell the already running application to un-minimize
205  * itself and let the new program know that it should Quit (since a GUI
206  * is already running).
207  */
208  virtual void WMHintCB(const WMHint hint,
209  const WMHintReason reason);
210 
211 
212  /**
213  * This method is useful when the connection to the secure gateway
214  * has been established as part of a web-launch of the VPN tunnel.
215  *
216  * If the client application wishes to be notified of the secure
217  * gateway to which the VPN has been established, this method should
218  * be overridden.
219  *
220  * If the client application is started and a tunnel is already active,
221  * this method also delivers the name of the secure gateway host.
222  */
223  virtual void deliverWebLaunchHostCB(const tstring &activeHost);
224 
225  /**
226  * This method is called when the preference to block untrusted
227  * servers is enabled and the current VPN server being connected
228  * to is untrusted. Clients should present an error to the user
229  * notifying them that the current connection to rtstrUntrustedServer
230  * is being blocked. The client should also provide a way for the
231  * user to change the preference to block untrusted servers.
232  *
233  * The user response must be indicated using setCertBlockedResponse
234  */
235  virtual void CertBlockedCB(const tstring &rtstrUntrustedServer) = 0;
236 
237  /**
238  * This method is called when connections to untrusted VPN servers
239  * is allowed by policies and the current VPN server being connected
240  * to is untrusted. Clients should present a warning to the user
241  * notifying them that the current connection to rtstrUntrustedServer
242  * is unsafe. The reason the VPN server is untrusted is provided in
243  * rltstrCertErrors. The client should provide a way for the user to
244  * connect once, connect and always trust or cancel the connection.
245  * If bAllowImport is set to false then the always trust option should
246  * not be presented to users.
247  *
248  * The user response must be indicated using setCertWarningResponse
249  */
250  virtual void CertWarningCB(const tstring &rtstrUntrustedServer,
251  const std::list<tstring> &rltstrCertErrors,
252  bool bAllowImport) = 0;
253 
254 #if defined(PLATFORM_WIN_APP)
255  /**
256  * Same as above but also passes the Server certificate DER for details display
257  */
258  virtual void CertWarningCB(const tstring &rtstrUntrustedServer,
259  const std::list<tstring> &rltstrCertErrors,
260  const std::vector<uint8_t> &rvServerCertDER,
261  bool bAllowImport) = 0;
262 #endif
263 
264  /**
265  * This method should be overridden by the client application to
266  * exercise some control over the delivery of events from the other
267  * protected methods in this class.
268  *
269  * This might be necessary in cases where a GUI/CLI is being written and
270  * the data from this API needs to be delivered in the GUI/CLI or main
271  * thread. In this case, you should override this method and when it
272  * is called by the API post an event to your event queue (message
273  * pump, etc.). After this event executes in your GUI/CLI or main thread,
274  * call the method ClientIfc::ProcessEvents to have events delivered
275  * to your client application.
276  */
277  virtual void EventAvailable();
278 
279 #if defined(MANUAL_PKCS12_IMPORT_SUPPORTED)
280  virtual void ImportPKCS12ResultCB(const std::vector<uint8_t> &certHash,
281  const tstring &tstrError);
282 #endif
283 #if defined(PLATFORM_ANDROID)
284  virtual void ClientCertificateCB(std::vector< std::pair<uint32_t, uint8_t*> > certList) = 0;
285  virtual void AgentDetachedCB();
286 #endif
287 
288 #if defined(VPNAPI_EVENT_NOTIFICATION_SUPPORTED)
289  /**
290  * Internal callback between ClientIfcBase and ClientIfc.
291  */
292  virtual void EventNotificationInternalCB(
293  const std::shared_ptr<CEventNotificationTlv>& spEventNtfctnTlv) = 0;
294 #endif
295 
296 
297  /**
298  * Internal methods for use by ClientIfc.
299  */
300 
301  void ResetQuarantinedReconnect();
302 
303  void ClientIfcTransmigration();
304 
305 public:
306 
307  bool attach(const ClientType clientType = ClientType_GUI,
308  const bool requestFullCapabilities = true,
309  const bool suppressAutoConnect = true,
310  const bool bSuppressEventAvailableCB = false);
311 
312  void detach();
313 
314  void ProcessEvents();
315 
316  bool hasFullCapabilities();
317 
318  bool isConnected(bool bSilent = false);
319 
320  bool isAvailable();
321 
322  std::list<tstring> getHostNames();
323 
324  std::list<HostEntry> getHostEntries();
325 
326  tstring getDefaultHostName();
327 
328  bool connect(
329 #if defined(HOST_DATA_SUPPORTED)
330  const IHostData& host);
331 #else
332  tstring host);
333 #endif
334 
335  bool connect(
336 #if defined(HOST_DATA_SUPPORTED)
337  const IHostData& host,
338 #else
339  tstring host,
340 #endif
341  unsigned int origin);
342 
343  bool setNewTunnelGroup(const tstring & group);
344 
345  void disconnect();
346 
347  void disconnect(VPNDisconnectReason disconnectEvent);
348 
349  void cancel();
350 
351  void resetStats();
352 
353  void getState();
354 
355  VPNState getCurrentVPNState();
356  VPNSubState getCurrentVPNSubState();
357  VPNSubState getPreviousVPNSubState();
358 
359  STATE getCurrentState();
360 
361  tstring getStateText();
362  static tstring getNoticeTypeText(MessageType msgType);
363 
364  static tstring getStateText(VPNState state,
365  VPNSubState subState = VPNSS_NORMAL,
366  NETENV_STATE netEnvState = NES_NETWORK_ACCESSIBLE,
367  const tstring& tstrConnectedHost = tstring());
368 
369  void setNetworkStates(NETENV_STATE netEnvState,
370  NETCTRL_STATE netCtrlState,
371  NETWORK_TYPE netType,
372  bool bACBrowserForCPRemediation,
373  bool bUpdateUI);
374  void refreshOperatingModeForCurrentNetStates();
375  NETENV_STATE getCurrentNetEnvState();
376  NETENV_STATE getPreviousNetEnvState();
377  NETCTRL_STATE getCurrentNetCtrlState();
378  NETWORK_TYPE getCurrentNetType();
379  bool isACBrowserForCPRemediation();
380 
381  static tstring getNetCtrlText(NETCTRL_STATE netCtrlState);
382  static tstring getNetEnvText(NETENV_STATE netEnvState,
383  bool bSimple = false);
384  static tstring getNetTypeText(NETWORK_TYPE netType);
385  static tstring getQuarantinedStatusText();
386  static tstring getNetworkStatusSimpleText(const NETENV_STATE netEnvState,
387  const NETCTRL_STATE netCtrlState);
388 
389  // can't be static due to requiring operating mode information
390  tstring getNetworkStatusText(const VPNState state,
391  const VPNSubState subState,
392  const NETENV_STATE netEnvState,
393  const NETCTRL_STATE netCtrlState);
394 
395  PreferenceInfo& getPreferences();
396 
397  bool savePreferences();
398 
399  void startStats();
400 
401  void stopStats();
402 
403  void UserSubmit();
404 
405  void setBanner(const tstring &banner);
406  void setBannerResponse(bool bResponse);
407 
408  void setPreConnectReminder(const tstring &tstrPreConnectReminder);
409  void setPreConnectReminderResponse();
410 
411  bool getUserResponse();
412  bool isUserResponseSet();
413 
414  void setCertBlocked(const tstring &tstrUntrustedServer);
415  void setCertWarning(const tstring &rtstrUntrustedServer,
416  const std::list<tstring> &rltstrCertErrors,
417  bool bAllowImport);
418 #if defined(PLATFORM_WIN_APP)
419  void setCertWarning(const tstring &rtstrUntrustedServer,
420  const std::list<tstring> &rltstrCertErrors,
421  const std::vector<uint8_t>& rvServerCertDER,
422  bool bAllowImport);
423 #endif
424  bool getCertImportResponse();
425 
426 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID) || defined(PLATFORM_CHROMEBOOK)
427  void setCertBanner(tstring tstrCertBannerSummary,
428  uint32_t nCertBannerCertLen,
429  const uint8_t *pCertBannerCertDer,
430  const std::list<tstring> &confirmReasons,
431  const std::list<CertConfirmReason> &confirmReasonEnums,
432  bool bImportAllowed);
433 
434  void setCertBannerResponse(bool bResponse, bool bImportCert);
435  void importServerCert(std::vector<uint8_t> certData);
436  bool setFipsMode(bool bEnableFips);
437 #if defined(PLATFORM_ANDROID)
438  bool setStrictMode(bool bEnableStrictMode);
439  bool setRevocationEnabled(bool bRevocationEnabled);
440  bool IsRevocationEnabled();
441 #endif // currently supported only for android
442 #endif
443 
444  void setUserPrompt(ConnectPromptInfo &ConnectPrompt);
445 
446 #if defined(PLATFORM_ANDROID)
447  void setClientCertResponse(std::vector< std::pair<uint32_t, uint8_t*> > &derList);
448  void setAgentDetached();
449  bool getClientCertificates();
450 #endif
451 
452 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID)
453  void setSCEPEnrollInProgress(bool bInProgress);
454  bool isSCEPEnrollInProgress();
455 #endif
456 
457 #if defined(MANUAL_PKCS12_IMPORT_SUPPORTED)
458  void setImportPKCS12Result(const std::vector<uint8_t> &certHash, const tstring &tstrError);
459  bool requestImportPKCS12(const std::vector<uint8_t> &data);
460  std::vector<uint8_t> importPKCS12WithPassword(const std::vector<uint8_t> &data, const tstring &password);
461 #endif
462 
463  void setCertBlockedResponse(bool bUnlock);
464  void setCertWarningResponse(bool bConnect, bool bImportCert);
465 
466  void insertStateToConnectPrompt(ConnectPromptInfo &ConnectPrompt);
467 
468  void ExitNotice(const tstring &tstrNotice, const int code = 0);
469 
470  void notice(const tstring &tstrNotice,
471  const MessageType type = MsgType_Info,
472  bool bClearLastMsg = false,
473  bool bForce = false,
474  bool bStateMsg = false,
475  bool bSensitiveMsg = false);
476 
477  void notice(MsgWithArg &notice,
478  const MessageType type = MsgType_Info,
479  bool bClearLastMsg = false,
480  bool bForce = false,
481  bool bStateMsg = false,
482  bool bSensitiveMsg = false);
483 
484  void getStats(void);
485 
486  void setStats(VPNStats &stats);
487 
488  void exportStats(const tstring &tstrFilePath);
489 
490  void initState(VPNState state,
491  VPNState previousState,
492  VPNSubState subState);
493 
494  void setState(VPNState state,
495  VPNState previousState,
496  VPNSubState subState = VPNSS_NORMAL,
497  bool bUpdateStateMsg = true,
498  bool bOnlyUpdateUI = false);
499 
500 #if defined(PROGRAM_DATA_IMPORT_SUPPORTED)
501  IACImporterAsync *createACImporter(IACImporterAsyncCB *pCallback);
502 #endif
503 
504  void setWMHint(WMHint hint,
505  WMHintReason reason);
506 
507  bool isLastConnectType (const ConnectPromptType connPromptType);
508 
509  bool isOperatingMode(OperatingMode opMode);
510  void setOperatingMode(OperatingMode opMode);
511  void unsetOperatingMode(OperatingMode opMode);
512 
513  bool CanRemediateCaptivePortal();
514  bool policyAllowsCaptivePortalRemediation();
515 
516  bool isEventShutdown();
517 
518  bool isUsingEventModel();
519 
520  time_t getLastDisconnectTime();
521 
522  ConnectPromptInfo getConnectPromptInfo();
523  void resetConnectPromptPasswordData();
524 
525  void setStandaloneConnection(bool isStandalone);
526 
527  void deliverActiveHost(const tstring &activeHost,
528  ConnectProtocolType vpnProtocol = PROTOCOL_TYPE_UNKNOWN,
529  bool bActiveHostFriendlyName = false);
530 
531  bool isVPNServiceReady();
532 
533  // reset last disconnect time indicator.
534  //
535  void resetLastDisconnectTime(time_t time = 1);
536 
537  void processMinimize();
538 
539  // cert enrollment
540  void setEnrollClientCert(CertObj* pCert);
541 
542  // Show user banner for cert import warning on linux
543  // SCEPIfc to ConnectMgr
544  void linuxCertImportWarnUser();
545 
546  // Response to cert warning on linux
547  // ConnectMgr to SCEPIfc
548  void linuxCertImportWarnUserResponse(bool bAccept);
549 
550  void setDefaultHost(tstring &host);
551 
552 #if defined(HOST_DATA_SUPPORTED)
553  void setDefaultHostProfile(const IHostData &hostProfile);
554  IHostData* getDefaultHostData();
555 #endif
556 
557  void setLastVpnError(VPNError vpnError);
558  VPNError getLastVpnError();
559 
560 #if defined(PLATFORM_ANDROID)
561  bool requestClientCertificates();
562 #endif
563 
564  bool requestImportLocalization(const tstring tstrLocale,
565  const std::vector<unsigned char> &MoFileData);
566 
567  // Start the Automatic Headend Selection operation
568  void startAHS(const unsigned int uiReason,
569  const ProxyIfc& proxy);
570  // statusReturnCode is a long to match the current type of STATUSCODE.
571  // It is not using a STATUSCODE directly so that we do not have to
572  // expose the header files for STATUSCODEs to ClientIfcBase.h
573  void AHSSelectedHost(const unsigned int uiReason,
574  const std::vector<tstring> &headendList,
575  const long statusReturnCode,
576  const tstring& extraInfo);
577  std::vector<tstring> getAHSHostList();
578  unsigned int getAHSState();
579  bool isAHSHasRun();
580  bool IsAHSCachingRestricted();
581 
582  bool suppressConnectionErrorPopups();
583 
584  tstring getCaptivePortalDetectedMsg();
585 
586  void setProxyAuthPrompts(ProxyIfc* pProxy,
587  const tstring& promptMsg);
588 
589 #if defined(INTERPROCESS_COMMUNICATION_SUPPORTED)
590  bool handleIpcMessage(CIpcMessage *pIpcMessage);
591 #if defined(VPNAPI_EVENT_NOTIFICATION_SUPPORTED)
592  void signalDisconnectedToEventNtfctnThread();
593 #endif
594 #endif
595  bool IsCsdTokenVerified() const;
596 
597 #if defined(PLATFORM_APPLE_SSLVPN) || defined(PLATFORM_ANDROID)
598  virtual void SCEPEnrollStartCB();
599  virtual void SCEPEnrollExitCB();
600 #endif
601 
602  void activateConnectMgrTunnelInitiationCompletionEvent();
603  bool isConnectRequestActive();
604  bool isConnectRequestCleanup();
605 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_CHROMEBOOK)
606  bool deleteProfileByName(const tstring &profileName);
607  tstring getProfileContents(const tstring &profileName);
608  bool importProfile(const tstring &profileName, const tstring &profileContents);
609 #endif
610 
611  bool syncProfileChange(const tstring &profileName);
612 
613 #if defined(CREDENTIAL_PREFILL_SUPPORTED)
614  bool hasPrefilledCredentials();
615  bool prefillCredentials(ConnectPromptInfo &connectPrompt);
616  void setPrefilledCredentials(CredentialPrefill *prefill);
617 #endif
618 
619 #if defined(PLATFORM_ANDROID) || defined(PLATFORM_APPLE_SSLVPN)
620  std::list<ManagedCertificate *> enumerateCertificates(CertificateType certType);
621  bool deleteCertificates(CertificateType certType, const std::list<std::string> &idList);
622  bool deleteServerCertificates(const std::list<std::string> &idList);
623 #endif
624 
625 #if defined(ANYCONNECT_USE_SNAK) && !defined(PLATFORM_WIN_APP)
626  std::list<ManagedCertificate *> enumerateSNAKCertificates(SNAK_CertType certType);
627  SNAK_CertType getSNAKCertType(CertificateType certType);
628  bool deleteClientCertificates(const std::list<std::string> &idList);
629 #endif
630 
631 #if defined(PLATFORM_APPLE_SSLVPN)
632  bool canUseBackupServers();
633 #endif
634 
635  tstring getConnectHost();
636 
637  tstring getMgmtTunnelHostname();
638 
639  VPN_TUNNEL_SCOPE getVpnTunnelScope();
640 
641  bool isStandaloneConnection();
642 
643  void sendSSoLogoutPrompt(ConnectPromptInfo &cpi);
644 
645  void setExternalSSOLogoutUrlFromAgent(const tstring& logoutUrl);
646 
647 private:
648 
649  //
650  // Private Member Data
651  //
652 
653 #if defined(VPNAPI_TRANSMIGRATION_SUPPORTED)
654  std::shared_ptr<CSharedAccessLock> m_spClientIfcInternalPtrSharedAccessLock;
655 #endif
656  std::unique_ptr<ClientIfcInternal> m_upClientIfcInternal;
657 
658 
659  //
660  // Private Member Methods
661  //
662 
663  // Prevent copying by declaring but not defining copy constructor and operator= methods.
664  //
665  ClientIfcBase(const ClientIfcBase& other);
666  ClientIfcBase& operator=(const ClientIfcBase& other);
667 };
668 
669 #endif // _CLIENTIFCBASE_
Definition: api.h:113
ConnectPromptType
Definition: api.h:244
Definition: PreferenceInfo.h:26
WMHintReason
Definition: api.h:220
VPNDisconnectReason
Definition: api.h:188
VPNState
Definition: api.h:146
Definition: ClientIfcBase.h:63
#define tstring
Definition: api.h:35
WMHint
Definition: api.h:201
Definition: ConnectPromptInfo.h:37
MessageType
Definition: api.h:108
OperatingMode
Definition: api.h:545
VPNSubState
Definition: api.h:170
VPNError
Definition: api.h:597
Definition: VPNStats.h:35